Data Structures
What kind of data can I store in R? Different types of objects that
can contain different types and sets of data:
- Scalar: numbers, characters, logical values
- Vector: sets of scalars (thus, numbers, characters,
logical)
- Matrix: two-dimensional set of scalars of same
type
- Data frame: collections of vectors of (possibly)
different types
- Array: multidimensional set of scalars of same
type
- List: combinations of scalars, vectors,
matrices…
We will go through all of these object types below. On top of that we
will also learn how to calculate the measures of central tendency and
variability with vectors.
Data Structures - Vectors
Let’s start with vectors. We want a vector of the numbers 1, 2, 3, 4
and 5. How do I assign this set of numbers to a vector?
The c() function
combines single values to a vector:
example_vec <- c(1, 2, 3, 4, 5)
example_vec
[1] 1 2 3 4 5
This also works for characters/strings:
country_code <- c("DE", "FR", "NL", "US", "UK")
country_code
[1] "DE" "FR" "NL" "US" "UK"
And it also works for a combination of numbers and characters:
example_vec2 <- c("Welcome", "to", "the", "lab", "in", "A", 5)
example_vec2
[1] "Welcome" "to" "the" "lab" "in" "A" "5"
What if we start with numbers?
example_vec3 <- c(1, 2, 3, 4, 5, "R can count!")
example_vec3
[1] "1" "2" "3" "4" "5" "R can count!"
Note that if you have a character
field in your vector, R will turn ALL values into character data! (You
can see that by the quotes around the values)
Let’s check the type of data by using the class()
command on example_vec3.
example_vec3 <- c(1, 2, 3, 4, 5, "R can count!")
class(example_vec3)
[1] "character"
You can use mathematical functions on each element in numeric
vectors/matrices etc.
example_vec <- c(1, 2, 3, 4, 5)
sqrt(example_vec) # Take the square root of each element in example_vec
[1] 1.000000 1.414214 1.732051 2.000000 2.236068
What about multiplication?
example_vec <- c(1, 2, 3, 4, 5)
example_vec * 10
[1] 10 20 30 40 50
There are also some functions that you can use on the whole
vector.
example_vec <- c(1, 2, 3, 4, 5)
sum(example_vec) # Question: What does sum() do?
[1] 15
length(example_vec) # Question: What does length() do?
[1] 5
Data Structures - Matrices
Matrices in R are two-dimensional
table objects. In R, matrices are always row by column. Like
roller coaster, Roman
Catholic or Ray
Charles).
In a matrix, all data must be of the same type. If you mix numeric
and character entries, the matrix will be all character just like in a
vector.
How do I create a matrix in R?
example_mat1 <- matrix(c(1, 2, 3, 4, 5, 6),
nrow = 3,
ncol = 2
)
example_mat1 # How did R fill the numbers in the matrix?
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
You could also change the options an let R fill the matrix by
rows (instead of columns):
example_mat2 <- matrix(c(1, 2, 3, 4, 5, 6),
nrow = 3,
ncol = 2,
byrow = T
)
example_mat2 # See the difference?
[,1] [,2]
[1,] 1 2
[2,] 3 4
[3,] 5 6
Or you could create a matrix from different vectors by using
column-bind on two or more vectors. It works similar to the
c() function but with vectors as input instead of
scalars.
Let’s first create two vectors of the same length:
vec1 <- c(1, 2, 3, 4, 5, 6)
vec2 <- c(7, 8, 9, 10, 11, 12)
# And now column-bind - cbind() - the two vectors.
example_mat3 <- cbind(vec1, vec2)
example_mat3
vec1 vec2
[1,] 1 7
[2,] 2 8
[3,] 3 9
[4,] 4 10
[5,] 5 11
[6,] 6 12
Similarly, we can row-bind – rbind() – the two
vectors:
vec1 <- c(1, 2, 3, 4, 5, 6)
vec2 <- c(7, 8, 9, 10, 11, 12)
example_mat4 <- rbind(vec1, vec2)
example_mat4
[,1] [,2] [,3] [,4] [,5] [,6]
vec1 1 2 3 4 5 6
vec2 7 8 9 10 11 12
Data Structures - Data frames
Data frames are two-dimensional
table objects, just like matrices. Most data you will analyze in R will
be in this form.
You can create data frames from vectors just like
cbind() using data.frame():
vec1 <- c(1, 2, 3, 4, 5, 6)
vec2 <- c(7, 8, 9, 10, 11, 12)
example_df1 <- data.frame(vec1, vec2)
example_df1
However, data frames are always column-bound vectors. In a data
frame, everything within a column has to be of the same data type. But
you can mix data types between columns:
vec1 <- c(1, 2, 3, 4, 5, 6)
vec2 <- c(7, 8, 9, 10, 11, 12)
vec3 <-
c(
"First Row",
"Second Row",
"Third Row",
"Fourth Row",
"Fifth Row",
"Sixth Row"
)
example_df2 <- data.frame(vec1, vec2, vec3)
example_df2
You can also name your columns/variables. Either when creating your
data frame:
vec1 <- c(1, 2, 3, 4, 5, 6)
vec2 <- c(7, 8, 9, 10, 11, 12)
vec3 <-
c(
"First Row",
"Second Row",
"Third Row",
"Fourth Row",
"Fifth Row",
"Sixth Row"
)
example_df3 <- data.frame(
variable_1to6 = vec1,
variable_7to12 = vec2,
variable_rows = vec3
)
example_df3
Or by renaming an existing data frame.
vec1 <- c(1, 2, 3, 4, 5, 6)
vec2 <- c(7, 8, 9, 10, 11, 12)
vec3 <-
c(
"First Row",
"Second Row",
"Third Row",
"Fourth Row",
"Fifth Row",
"Sixth Row"
)
example_df3 <- data.frame(vec1, vec2, vec3)
# Rename the variables of an existing data frame
names(example_df3) <- c("variable.1", "variable.2", "variable.3")
example_df3
vec1 <- c(1, 2, 3, 4, 5, 6)
vec2 <- c(7, 8, 9, 10, 11, 12)
vec3 <-
c(
"First Row",
"Second Row",
"Third Row",
"Fourth Row",
"Fifth Row",
"Sixth Row"
)
example_df3 <- data.frame(vec1, vec2, vec3)
names(example_df3) <- c("variable.1", "variable.2", "variable.3")
We can also add a new variable to an existing data frame. We simply
create a data frame which consists of a data frame and a vector:
example_df4 <-
data.frame(example_df3,
variable_4 = c(90, 91, 92, 93, 94, 95))
example_df4
Data Structures - Arrays
These are like matrices, except that they are typically
three-dimensional. You’re not going to see many of these, but we’ll
introduce them for completeness. Here is an illustration of what a
three-dimensional array could look like:

You can think of 10 3 x 5 bingo cards, that all display spaces 1
through 15 for example, as an array. If I were to display that in R, I
would use the array function to write:
bingo_array <- array(seq(1, 15, 1),
dim = c(3, 5, 10))
bingo_array
The general syntax for this function is
array(values you want to array, dim = (row, column, height)).
Data Structures - Lists
List objects can contain a series of the other objects we just
learned about. A single list can contain a value, a vector, a matrix,
AND a dataframe - or many of each!
How do I make a list?
Use the list()
function!
# create a vector
example_vec <- c(1, 2, 3, 4, 5, 6, 7, 8)
# create a matrix
example_mat <- matrix(c(1, 2, 3, 4, 5, 6),
nrow = 3,
ncol = 2)
# create an array
example_array <- array(seq(1, 15, 1), dim = c(3, 5, 10))
example_vec3 <- c(1, 2, 3, 4)
## Store all objects in a list
example_list <- list(example_vec, example_mat, example_array)
example_list
Selecting elements in a vector, matrix or data.frame
Sometimes we want to select single or multiple data entries from our
objects. We can do this by selecting elements via [].
Let’s first do it with a vector. Remember our country_code
vector?
country_code <- c("DE", "FR", "NL", "US", "UK")
country_code
[1] "DE" "FR" "NL" "US" "UK"
country_code <- c("DE", "FR", "NL", "US", "UK")
Let’s say we only want to select the “US”. We can achieve this by
accessing the value via its position in the vector:
country_code[4]
[1] "US"
Now we want to select all values but the “US”:
country_code[-4]
[1] "DE" "FR" "NL" "UK"
You can pass multiple indexes as a vector:
country_code[c(1, 2, 3)]
[1] "DE" "FR" "NL"
1:3 generates the vector c(1, 2, 3) a bit
quicker.
country_code[1:3]
[1] "DE" "FR" "NL"
If we want the values “DE”, “FR”, and “US”, a sequence does not
really help. But we can put a vector with a combination of a sequence
and some other values in the square brackets:
country_code[c(1:2, 4)]
[1] "DE" "FR" "US"
Selecting items in two-dimensional objects
We can access values of a matrix similarly. However, we need to think
of one additional dimension.
example_mat <- matrix(c(1, 2, 3, 4, 5, 6),
nrow = 3,
ncol = 2)
example_mat
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
Generally, we type object[row, column] to access
specific rows and columns. To see how this works, let’s have a look at
our example_mat:
Now we want to access the value 6. It’s in the third row and the
second column.
example_mat[3, 2]
[1] 6
We could also select an entire column (and use it like a vector).
example_mat[, 2]
[1] 4 5 6
By accessing values with the [] square brackets, we
could also replace values. Let’s say we want to recode the entire first
column in example_mat3 to 99:
example_mat[, 1] <- 99
example_mat
[,1] [,2]
[1,] 99 4
[2,] 99 5
[3,] 99 6
example_mat <- matrix(c(1, 2, 3, 4, 5, 6),
nrow = 3,
ncol = 2)
example_mat[, 1] <- 99
# And we want to recode the first and the third value in the second column
# to 91 and 100
example_mat[c(1, 3), 2] <- c(91, 100)
example_mat
[,1] [,2]
[1,] 99 91
[2,] 99 5
[3,] 99 100
Selection with conditions
This is a good start to select and recode data in an object. However,
it might be a bit exhausting (maybe even impossible) to always look up
the exact position in the object.
Luckily, R let’s us also select elements based on conditions. Instead
of the position we put a condition in the [] square brackets.
- For this we can use several conditions:
- Is equal to:
==
- Is not:
!=
- Is smaller than:
<
- Is greater than:
>
- Is smaller or equal to:
<=
- Is greater or equal to:
>=
- Conditions can be combined with and and/or or statements
So how do conditions work? Let’s create a matrix to work with
vec1 <- c(1, 2, 3, 4, 5, 6)
vec2 <- c(7, 8, 9, 10, 11, 12)
# And now column-bind (cbind()) the two vectors.
example_mat <- cbind(vec1, vec2)
example_mat
vec1 vec2
[1,] 1 7
[2,] 2 8
[3,] 3 9
[4,] 4 10
[5,] 5 11
[6,] 6 12
example_mat > 9 # This returns TRUE or FALSE for each value in the object.
vec1 vec2
[1,] FALSE FALSE
[2,] FALSE FALSE
[3,] FALSE FALSE
[4,] FALSE TRUE
[5,] FALSE TRUE
[6,] FALSE TRUE
Now if we put this condition in square brackets we get the values for
which the condition is true.
example_mat[example_mat > 9]
[1] 10 11 12
Exercise II: Selecting and recoding elements
Here comes the second round of exercises:
Create two vectors vec1 and vec2.
vec1 should contain 1, 56, 23, 89, -3 and 5 (in that
order).
vec2 contains 24, 78, 32, 27, 8 and 1.
Now select elements of vec1 that are greater than 5
or smaller than 0.
Next set vec1 to zero if vec2 is
greater than 30 and smaller or equal to 32.
Please solve all three steps in the next code chunk.
vec1
[1] 1 56 0 89 -3 5
Working with data.frames
Working with data frames is similar to working with matrices and
vectors.
Loading and manipulating data
Usually (and especially for this class) we want to work with existing
datasets. R knows and can load most of the standard formats of datasets,
like .csv, .xlsx (Excel), .dta
(Stata), .sav (SPSS) and many more.
So far we only used R’s base functions. In order to use some more
sophisticated or special R functions, we need to load libraries or
packages first. Think of these libraries as extra apps that you can load
on your smartphones to extend its functionality.
Right now, we want to load the dataset. In order to use the standard
but foreign datasets we need the foreign package.
First, we want to have a look at what the package can do.
packageDescription("foreign")
Package: foreign
Priority: recommended
Version: 0.8-81
Date: 2020-12-22
Title: Read Data Stored by 'Minitab', 'S', 'SAS', 'SPSS', 'Stata', 'Systat', 'Weka', 'dBase', ...
Depends: R (>= 4.0.0)
Imports: methods, utils, stats
Authors@R: c( person("R Core Team", email = "R-core@R-project.org", role = c("aut", "cph", "cre")), person("Roger", "Bivand",
role = c("ctb", "cph")), person(c("Vincent", "J."), "Carey", role = c("ctb", "cph")), person("Saikat", "DebRoy",
role = c("ctb", "cph")), person("Stephen", "Eglen", role = c("ctb", "cph")), person("Rajarshi", "Guha", role =
c("ctb", "cph")), person("Swetlana", "Herbrandt", role = "ctb"), person("Nicholas", "Lewin-Koh", role = c("ctb",
"cph")), person("Mark", "Myatt", role = c("ctb", "cph")), person("Michael", "Nelson", role = "ctb"), person("Ben",
"Pfaff", role = "ctb"), person("Brian", "Quistorff", role = "ctb"), person("Frank", "Warmerdam", role = c("ctb",
"cph")), person("Stephen", "Weigand", role = c("ctb", "cph")), person("Free Software Foundation, Inc.", role =
"cph"))
Contact: see 'MailingList'
Copyright: see file COPYRIGHTS
Description: Reading and writing data stored by some versions of 'Epi Info', 'Minitab', 'S', 'SAS', 'SPSS', 'Stata', 'Systat',
'Weka', and for reading and writing some 'dBase' files.
ByteCompile: yes
Biarch: yes
License: GPL (>= 2)
BugReports: https://bugs.r-project.org
MailingList: R-help@r-project.org
URL: https://svn.r-project.org/R-packages/trunk/foreign/
NeedsCompilation: yes
Packaged: 2020-12-22 13:59:32 UTC; hornik
Author: R Core Team [aut, cph, cre], Roger Bivand [ctb, cph], Vincent J. Carey [ctb, cph], Saikat DebRoy [ctb, cph], Stephen
Eglen [ctb, cph], Rajarshi Guha [ctb, cph], Swetlana Herbrandt [ctb], Nicholas Lewin-Koh [ctb, cph], Mark Myatt
[ctb, cph], Michael Nelson [ctb], Ben Pfaff [ctb], Brian Quistorff [ctb], Frank Warmerdam [ctb, cph], Stephen
Weigand [ctb, cph], Free Software Foundation, Inc. [cph]
Maintainer: R Core Team <R-core@R-project.org>
Repository: CRAN
Date/Publication: 2020-12-22 14:59:20 UTC
Built: R 4.1.2; x86_64-apple-darwin17.0; 2021-11-01 20:59:13 UTC; unix
-- File: /Library/Frameworks/R.framework/Versions/4.1/Resources/library/foreign/Meta/package.rds
# Ok this seems to be useful. So let's load the package to use it.
library(foreign)
You will often come across datasets which are stored as Stata data
files. Those files have the extension .dta.
Right now, we want to load the data set called
weather_data_germany_2021.dta which is already stored the
raw_data folder in our directory:
weather_data <- read.dta("raw_data/weather_data_germany_2021.dta")
The data contains yearly temperature averages of German cities as
well as their geographical location (longitude and latitude). It comes
from the “Deutscher Wetterdienst” and you can find it here. Now
that we have loaded the data, we can have a look at it.
With head()we can look at the first six rows of the data
set:
head(weather_data)
But we can also look at the entire data set:
If we only want to look at the variable names, we can use
names():
names(weather_data)
Now we can use our selecting abilities on a data frame. As before we
can select elements via their numeric position:
weather_data[1, 2] # first row, second column
weather_data[1:3, 1] # rows 1-3, first column
Additionally, as columns usually have names in data frames, we can
use the column names to select values in two ways.
First, we can put the column name in square brackets instead of a
column number:
weather_data[1, "city"]
We can also look at two variables at once:
Second, we can also select an entire column by using the
$ operator with the column name:
data.frame_name$column_name. Just like this:
weather_data$mean_temp
Columns from data frames are essentially vectors. We can use all the
operations and functions we can use for vectors (depending on their
class.)
weather_data$mean_temp[1] # For example, we can select an element of the vector
What if we want to add a new variable? Let’s create a variable named
“cold”.
weather_data$cold <- 0
# What does this do?
weather_data$cold
Now, we want to recode “cold” to 1 for cities whose mean temperature
is lower than 8 degrees Celsius.
weather_data$cold <- 0
weather_data$cold[weather_data$mean_temp < 8] <- 1
# Let's have a look at both variables:
weather_data[, c("city", "mean_temp", "cold")]
Calculating Measures of Central Tendency and Variability
Let’s look at the Measures of Central Tendency and Variability from
the lecture (starting at slide 17).
Consider the following vector:
example_vec <- c(1, 2, 3, 4, 5)
How could we calculate the mean of example_vec?
We could simply calculate it “by hand”:
(1 + 2 + 3 + 4 + 5) / 5
But this is not very useful if we look at an actual vector in our
data frame, e.g., mean temperature:
weather_data$mean_temp
Typing up all the entries individually would take a lot of time. We
could use two functions that we already have seen, sum and length.
sum(weather_data$mean_temp) / length(weather_data$mean_temp)
Fortunately, R provides a much easier way to calculate a mean:
mean(weather_data$mean_temp) # That was easy.
But be sure that your vector is numeric. Could you calculate the mean
of city?
weather_data$city
Let’s try to calculate the mean.
mean(weather_data$city)
It does not work! And even by hand we could not calculate the mean of
character valued vectors.
Here is an overview over functions for measures of centrality and
variability:
- Mean:
mean()
- Median:
median()
- Variance:
var()
- Standard Deviation:
sd()
- Range:
range()
- Inter-quartile range:
IQR()
You can try them out here:
# Median
median(weather_data$mean_temp)
# Variance
var(weather_data$mean_temp)
# Standard deviation
sd(weather_data$mean_temp)
# Range
range(weather_data$mean_temp)
# Inter Quartile Range (IQR)
IQR(weather_data$mean_temp)
Unfortunately, there is no direct function to get the mode. The
solutions you will find online are all a bit advanced. So the easiest
solution is to look for the mode using a frequency table.
table(weather_data$cold)
Error in table(weather_data$cold) : object 'weather_data' not found
The table() function shows you how often each value is
in the vector. You can now identify the most frequent value.
Exercise III: Manipulating data
Now we will work with the weather_data data set. It is
already loaded for you and you can use it right away.
Show the variable mean_temp if it is over
10.
Generate a new variable and call it hot that is zero
for mean temperature < 10 and 1 for mean
temperature > 10 degree Celsius.
Have a look at your data set.
Please solve all three steps in the next code chunk.
Exercise IV: Subsetting
This is a little trickier: Can you find the hottest and coldest city
in Germany 2021?
Hint: The functions min() and max() help
you to find the minimum and maximum values of a vector or variable.
Combine that with your newly learned subsetting skills and you’ll find
the answer.
Exercise V: Measures of central tendency
We will continue working with the weather data set
- Calculate the mean value of latitude and save the result as
mean_latitude.
mean_latitude <- mean(weather_data$latitude)
mean_latitude
[1] 50.77254
- Calculate the variance of latitude and save the result as
var_latitude.
var_latitude <- var(weather_data$latitude)
var_latitude
[1] 3.665423
- Calculate the standard deviation of latitude and save the result as
sd_latitude.
sd_latitude <- sd(weather_data$latitude)
sd_latitude
[1] 1.914529
Plotting data
Let’s have a short look at our data again. Remember:
head() shows you the first six entries of your data. It is
very useful to get a look at the data structure when you have a lot of
rows in your dataset.
head(weather_data)
Plots for bivariate distributions
Scatterplots
Now we can create a simple scatterplot:
plot(
x = weather_data$longitude,
y = weather_data$mean_temp
)
To get a nicer plot, we can adjust many things. We suggest to always
explicitly make those adjustments in the same order.
plot(
x = weather_data$longitude,
y = weather_data$mean_temp,
type = "p", # This explicitly says that we want points. You could also try "l".
main = "Mean temperatures of German cities", # This adds a title to the plot
xlab = "Longitude (West - East)", # This labels the x-axis.
ylab = "Mean Temperature in 2021", # What does this do then?
las = 1, # This affects the tick labels of the y-axis.
pch = 19, # Here we choose what symbols we want to plot.
col = "black", # What color should the symbols have?
frame = F # No box around the plot.
)
Adding Color to Plots with Viridis
We can also adjust the colors. Let’s highlight Mannheim!
Pro Tip: To color up your data
visualizations, use the
viridis-package.
Viridis colors make it easier to read by those with colorblindness
and print well in greyscale. You probably don’t want to have plots like
this:

We first need a vector that gives us the right colors with respect to
the city variable.
library(viridis)
Loading required package: viridisLite
Now we can use this vector to specify the color respective to
Mannheim:
plot(
x = weather_data$longitude,
y = weather_data$mean_temp,
type = "p", # This explicitly says that we want points. You could also try "l".
main = "Mean temperatures of German cities", # This adds a title to the plot
xlab = "Longitude (West - East)", # This labels the x-axis.
ylab = "Mean Temperature in 2021", # What does this do then?
las = 1, # This affects the tick labels of the y-axis.
pch = 19, # Here we choose what symbols we want to plot.
col = mannheim_color, # Instead of just black we now use the color vector.
frame = F # No frame around the plot.
)
Now that we use different colors, we also need a legend to know which
color is which.
plot(
x = weather_data$longitude,
y = weather_data$mean_temp,
type = "p", # This explicitly says that we want points. You could also try "l".
main = "Mean temperatures of German cities", # This adds a title to the plot
xlab = "Longitude (West - East)", # This labels the x-axis.
ylab = "Mean Temperature in 2021", # What does this do then?
las = 1, # This affects the tick labels of the y-axis.
pch = 19, # Here we choose what symbols we want to plot.
col = mannheim_color, # Instead of just black we now use the color vector.
frame = F # No frame around the plot.
)
legend(
"bottomleft", # Locate the legend in the topleft corner.
legend = c("Mannheim", "other"), # Give it labels.
pch = 19, # Specify symbols as in the scatterplot.
col = two_colors, # Specify colors.
bty = "n" # No box around the legend.
)
plot(
x = weather_data$longitude,
y = weather_data$mean_temp,
type = "p", # This explicitly says that we want points. You could also try "l".
main = "Mean temperatures of German cities", # This adds a title to the plot
xlab = "Longitude (West - East)", # This labels the x-axis.
ylab = "Mean Temperature in 2021", # What does this do then?
las = 1, # This affects the tick labels of the y-axis.
pch = 19, # Here we choose what symbols we want to plot.
col = mannheim_color, # Instead of just black we now use the color vector.
frame = F # No frame around the plot.
)
# we want to label the point that refers to Mannheim
# We can do that with the text() function,
# But we need to subset the data, so that only Mannheim gets labelled,
# and no other city
text(
x = weather_data$longitude[weather_data$city == "Mannheim"], # subset Mannheim
y = weather_data$mean_temp[weather_data$city == "Mannheim"], # subset Mannheim
labels = "Mannheim", # label Mannheim as "Mannheim"
pos = 4 # position the label right to the point
)
Plots for univariate distributions
Histograms
Now we want to visualize mean temperature with a histogram. This is
how you get a standard histogram:
hist(x = weather_data$mean_temp) # That's intuitive, but does not look too great
Again, we can adjust many things to make it nicer.
hist(
x = weather_data$mean_temp, # For a histogram we only specify x.
breaks = 50, # specify the number of bins
main = "A Histogram",
xlab = "Mean temperature in degree Celsius",
ylab = "Number of observations",
las = 1, # shift the y-axis labels
col = viridis(1), # One color only (first color from viridis)
border = "white" # That's the color of the bin borders.
)
Density Plots
We can also create density plots.
plot(
density(weather_data$mean_temp), # density() takes care of x, y and type.
main = "A Simple Density Plot",
xlab = "Mean temperature in degree Celsius",
ylab = "", # The y-axis is not really meaningful here.
col = viridis(1),
lwd = 2, # Control the width of the line
frame = F,
yaxt = "n" # Remove the y-axis.
)
And we can also fill the are underneath the curve:
plot(
density(weather_data$mean_temp), # density() takes care of x, y and type.
main = "A Simple Density Plot",
xlab = "Mean temperature in degree Celsius",
ylab = "", # The y-axis is not really meaningful here.
col = viridis(1),
lwd = 2, # Control the width of the line
frame = F,
yaxt = "n" # Remove the y-axis.
)
polygon(density(weather_data$mean_temp),
col = viridis(1, alpha = 0.5) # same color but 50% transparent
)
…and Boxplots
boxplot(
x = weather_data$mean_temp, # As for histograms we only specify x.
main = "Boxplot of Mean temperature in degree Celsius",
ylab = "Mean temperature in degree Celsius",
las = 1,
col = plasma(1),
frame = F
)
Or a horizontal boxplot.
boxplot(
x = weather_data$mean_temp,
horizontal = T, # With horizontal = T we rotate the boxplot.
main = "Horizontal Boxplot of Mean temperature in degree Celsius",
xlab = "Mean temperature in degree Celsius",
las = 1,
frame = F
)
You learned in the lecture that boxplots have some disadvantages.
Violin plots are a very nice
alternative!
This is how you get them:
library(vioplot)
vioplot(
x = weather_data$mean_temp,
horizontal = T, # With horizontal = T we rotate the boxplot.
main = "Horizontal Violinplot of Mean temperature in degree Celsius",
xaxt = "n",
xlab = "Mean temperature in degree Celsius",
bty = "n",
axes = FALSE,
names = "",
border = NA
)
Exercise VI: Plotting
Okay, last round of exercises for today:
- Make a histogram of the latitude variable.

- Make the plot nice looking (Name the axes, main title, colors…)
hist(
x = weather_data$latitude, # For a histogram we only specify x.
breaks = 50, # specify the number of bins
main = "A Histogram",
xlab = "Latitude",
ylab = "Number of observations",
las = 1, # shift the y-axis labels
col = viridis(1), # One color only (first color from viridis)
border = "white" # That's the color of the bin borders.
)

LS0tCnRpdGxlOiAiUU0gMjAyMiBXZWVrIDE6PGJyPkdldHRpbmcgU3RhcnRlZCB3aXRoIFIiCmF1dGhvcjogIk9saXZlciBSaXR0bWFubjxicj5Eb21hbnRhcyBVbmR6xJduYXM8YnI+TGlvbiBCZWhyZW5zPGJyPiIKZGF0ZTogIlNlcHRlbWJlciA3IHwgOCB8IDksIDIwMjIiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNzczogY3NzL2xhYi5jc3MKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY3NzOiBjc3MvbGFiLmNzcwotLS0KCiMjIExlYXJuaW5nIGdvYWxzIG9mIHRoZSBmaXJzdCB3ZWVrCgogIDEuIFdoYXQgYXJlIFIsIFJTdHVkaW8sIGFuZCBHaXQ/CiAgMi4gSG93IHRvIHVzZSAqKlIgYXMgYSBiYXNpYyBjYWxjdWxhdG9yKio/CiAgMy4gV2hhdCBhcmUgKipPYmplY3RzIGluIFIqKj8KICA0LiBTb21ldGhpbmcgYWJvdXQgKipSIERhdGEgc3RydWN0dXJlcyoqCiAgICAgIC0gVmVjdG9ycwogICAgICAtIE1hdHJpY2VzCiAgICAgIC0gRGF0YSBmcmFtZXMKICAgICAgLSBBcnJheXMKICAgICAgLSBMaXN0cwogIDUuICoqU2VsZWN0aW5nIEVsZW1lbnRzKiogaW4gYSB2ZWN0b3IsIG1hdHJpeCBvciBkYXRhIGZyYW1lCiAgNi4gV29ya2luZyB3aXRoICoqZGF0YSBmcmFtZXMqKgogICAgICAtIExvYWRpbmcgZGF0YSAKICAgICAgLSBNYW5pcHVsYXRpbmcgZGF0YQogIDcuIENhbGN1bGF0aW5nICoqTWVhc3VyZXMgb2YgQ2VudHJhbCBUZW5kZW5jeSBhbmQgVmFyaWFiaWxpdHkqKgogIDguICoqUGxvdHRpbmcgZGF0YSoqIGFuZCBzYXZpbmcgcGxvdHMKIAoKCiMjIFdoYXQgYXJlIFIsIFJTdHVkaW8sIGFuZCBHaXQ/CgojIyMgV2hhdCBpcyAqKlIqKj8KCmBSYCBpcyBhIHByb2dyYW1taW5nIGxhbmd1YWdlIGRlc2lnbmVkIHRvIGhlbHAgeW91IHBlcmZvcm0gc3RhdGlzdGljYWwgYW5hbHlzaXMsIGNyZWF0ZSBncmFwaGljcywgYW5kIGxhdGVyIG9uIHdyaXRlIHlvdXIgb3duIHN0YXRpc3RpY2FsIHNvZnR3YXJlLiBgUmAgaXMgYmVjb21pbmcgaW5jcmVhc2luZ2x5IHBvcHVsYXIgYW5kIGtub3dsZWRnZSBvZiBSIHdpbGwgaGVscCB5b3Ugb24gdGhlIGpvYiBtYXJrZXQuIGBSYCBpcyBwcm9iYWJseSB0aGUgbW9zdCB2ZXJzYXRpbGUgc3RhdGlzdGljYWwgdG9vbCBvdXQgdGhlcmUgKGFuZCBpdCdzIGZyZWUgYW5kIG9wZW4tc291cmNlIHNvIHlvdSBjYW4gbGl0ZXJhbGx5IHVzZSBpdCBhbnl3aGVyZSkuIEl0IGlzIGZvciBleGFtcGxlIHVzZWQgaW4gYWxsIGZpZWxkcyBvZiBhY2FkZW1pYSwgZnJvbSBiaW9sb2d5IHRvIGVjb25vbWljcywgYW5kIG91dHNpZGUgYWNhZGVtaWEgaW5jbHVkaW5nCgogLSBXYWxsc3RyZWV0CiAtIFRoZSBFY29ub21pc3QKIC0gW0JCQ10oaHR0cHM6Ly9ibG9nLnJldm9sdXRpb25hbmFseXRpY3MuY29tLzIwMTgvMDYvZnQtYmJjLXVzZXMtci5odG1sKQogLSBHb29nbGUgQW5hbHl0aWNzCiAtIE5ZIFRpbWVzIGdyYXBoaWNzIGRlcGFydG1lbnQKIAogCiMjIyBXaGF0IGlzICoqUlN0dWRpbyoqPwoKUlN0dWRpbyBpcyBhIGdyZWF0IGdyYXBoaWNhbCB1c2VyIGludGVyZmFjZSBmb3IgYFJgLiBJbiByZWNlbnQgeWVhcnMsIGEgZ3Jvd2luZyBudW1iZXIgb2YgZmVhdHVyZXMgaGF2ZSBiZWVuIGFkZGVkIHRvIHRoaXMgZ3JhcGhpY2FsIHVzZXIgaW50ZXJmYWNlLCB3aGljaCBtYWtlcyBpdCB0aGUgcHJlZmVycmVkIGNob2ljZSBmb3IgbGVhcm5pbmcgYFJgLCBlc3BlY2lhbGx5IGFtb25nIGJlZ2lubmVycy4gWW91IGNhbiB0aGluayBhYm91dCBpdCBhcyBgUmAgYmVpbmcgdGhlIGVuZ2luZSBvZiB0aGUgY2FyIGFuZCBSU3R1ZGlvIGJlaW5nIHRoZSBkYXNoYm9hcmQuIAoKIyMjIFdoYXQgYXJlICoqUlN0dWRpbyBQcm9qZWN0cyoqPwoKUlN0dWRpbyBwcm9qZWN0cyBtYWtlIGl0IHN0cmFpZ2h0Zm9yd2FyZCB0byBkaXZpZGUgeW91ciB3b3JrIGludG8gbXVsdGlwbGUgY29udGV4dHMsIGVhY2ggd2l0aCBpdHMgb3duIHdvcmtpbmcgZGlyZWN0b3J5LCB3b3Jrc3BhY2UsIGhpc3RvcnksIGFuZCBzb3VyY2UgZG9jdW1lbnRzLiBBIHByb2plY3QgaXMgYmFzaWNhbGx5IGEgZm9sZGVyIG9uIHlvdXIgY29tcHV0ZXIgdGhhdCBob2xkcyBhbGwgdGhlIGZpbGVzIHJlbGV2YW50IHRvIGEgcGFydGljdWxhciBwaWVjZSBvZiB3b3JrLiBXb3JraW5nIGluIFJTdHVkaW8gUHJvamVjdHMgaGFzIG11bHRpcGxlIGFkdmFudGFnZXM6CgogIC0gT25jZSBhbiBSU3R1ZGlvIFByb2plY3QgaXMgc2V0IHVwLCB5b3UgZG8gbm90IGhhdmUgdG8gd29ycnkgYWJvdXQgeW91ciB3b3JraW5nIGRpcmVjdG9yeSBhbnltb3JlLgogIC0gV2hlbiBvcGVuaW5nIGFuIFJTdHVkaW8gUHJvamVjdCwgYSBuZXcgYFJgIHNlc3Npb24gKHByb2Nlc3MpIGlzIHN0YXJ0ZWQuIFRoaXMgbWFrZXMgc3VyZSB0aGF0IHRoaW5ncyB5b3UgZG8gaW4gZGlmZmVyZW50IHByb2plY3RzIGRvIG5vdCBtZXNzIHVwLgogIC0gWW91IGNhbiBvcGVuIGFuZCB3b3JrIHdpdGggbXVsdGlwbGUgUlN0dWRpbyBwcm9qZWN0cyBhdCB0aGUgc2FtZSB0aW1lLgogIC0gUlN0dWRpbyBwcm9qZWN0cyBjYW4gZWFzaWx5IGJlIGV4cG9ydGVkIHRvIGFuZCBpbXBvcnRlZCBmcm9tIEdpdEh1Yi4KCgojIyMgV2hhdCBhcmUgKipHaXQqKiBhbmQgKipHaXRIdWIqKj8KCkdpdCBpcyBhIHZlcnNpb24gY29udHJvbCBzeXN0ZW0gdGhhdCBtYWtlcyBpdCBlYXN5IHRvIHRyYWNrIGNoYW5nZXMgYW5kIHdvcmsgb24gY29kZSBjb2xsYWJvcmF0aXZlbHkuIEdpdEh1YiBpcyBhIGhvc3Rpbmcgc2VydmljZSBmb3IgYGdpdGAuIFlvdSBjYW4gdGhpbmsgb2YgaXQgYXMgYSBwdWJsaWMgRHJvcGJveCBmb3IgY29kZSBidXQgb24gc3Rlcm9pZHMuIFdpdGggdmVyc2lvbiBjb250cm9sLCB5b3Ugd2lsbCBidWlsZCB5b3VyIHByb2plY3RzIHN0ZXAtYnktc3RlcCwgYmUgYWJsZSB0byBjb21lIGJhY2sgdG8gYW55IHZlcnNpb24gb2YgdGhlIHByb2plY3QsIGFuZCBhY2NvbXBhbnkgZXZlcnl0aGluZyB3aXRoIGh1bWFuLXJlYWRhYmxlIG1lc3NhZ2VzLiAKCkFzIGEgc3R1ZGVudCwgeW91IGV2ZW4gZ2V0IHVubGltaXRlZCBwcml2YXRlIHJlcG9zaXRvcmllcyB3aGljaCB5b3UgY2FuIHVzZSBpZiB5b3UgZG9uJ3QgZmVlbCBsaWtlIHNoYXJpbmcgeW91ciBjb2RlIHdpdGggdGhlIHJlc3Qgb2YgdGhlIHdvcmxkICh5ZXQpLiBXZSB3aWxsIHVzZSBwcml2YXRlIHJlcG9zaXRvcmllcyB0byBkaXN0cmlidXRlIGNvZGUgYW5kIGFzc2lnbm1lbnRzIHRvIHlvdS4gQW5kIHlvdSB3aWxsIHVzZSBpdCB0byBrZWVwIHRyYWNrIG9mIHlvdXIgY29kZSBhbmQgY29sbGFib3JhdGUgaW4gdGVhbXMuIAoKV2l0aCBnaXQsIHdyaXRpbmcgY29kZSBmb3IgYSBwcm9qZWN0IHdpbGwgbG9vayBzb21ld2hhdCBsaWtlIHRoaXM6CgohW10oaW1hZ2VzL2xlZ28tc3RlcHMtY29tbWl0LW1lc3NhZ2VzLnBuZykKCgojIyMgV2hhdCBpcyBhICoqR2l0IFJlcG9zaXRvcnkqKj8gCgpBIEdpdCByZXBvc2l0b3J5IGlzIGEgc3BhY2Ugd2hlcmUgeW91IHN0b3JlIGFuZCBtYW5hZ2UgYSBwcm9qZWN0LiBJdCBjb250YWlucyBhbGwgb2YgeW91ciBwcm9qZWN0J3MgZmlsZXMgYW5kIHN0b3JlcyBlYWNoIGZpbGUncyByZXZpc2lvbiBoaXN0b3J5LiBJdCdzIGNvbW1vbiB0byByZWZlciB0byBhIHJlcG9zaXRvcnkgYXMgYSByZXBvLiAKCldlIHdpbGwgeW91IG9uZSByZXBvc2l0b3J5IGZvciBlYWNoIGxhYiBhbmQgb25lIHJlcG9zaXRvcnkgZm9yIGVhY2ggaG9tZXdvcmsgYXNzaWdubWVudC4gWW91IGNhbiBkaXJlY3RseSBpbXBvcnQgKCJwdWxsIikgcmVwb3NpdG9yaWVzIHZpYSBSU3R1ZGlvIGFuZCBzYXZlIHRoZW0gb24geW91ciBjb21wdXRlci4gSWYgeW91IGNoYW5nZWQgc29tZXRoaW5nIGluIHlvdXIgcHJvamVjdCwgeW91IGNhbiBlYXNpbHkgdXBsb2FkICgicHVzaCIpIHRoZSBuZXcgdmVyc2lvbiB0byBHaXRIdWIuIEdpdEh1YiB3aWxsIGtlZXAgdHJhY2sgb2YgYWxsIGNoYW5nZXMgeW91IG1hZGUgb3ZlciB0aW1lIHdpdGhpbiB5b3VyIHByb2plY3QuCgoKIyMgV29ya2Zsb3cgb3ZlcnZpZXcKCk91ciB3b3JrZmxvdyB3aWxsIGFwcGVhciBhIGJpdCB0cmlja3kgYXQgdGhlIGJlZ2lubmluZyBidXQgd2UgYXJlIHN1cmUgdGhhdCB5b3Ugd2lsbCBoYW5kbGUgaXQgd2l0aCBlYXNlIHZlcnkgc29vbi4gV2UgYXNzdW1lIHRoYXQgYnkgbm93IHlvdSBkb3dubG9hZGVkIGFuZCBpbnN0YWxsZWQgUiBhbmQgUnN0dWRpbyBhbmQgaGF2ZSB5b3VyIHBlcnNvbmFsIEdpdEh1YiBhY2NvdW50LgoKVGhlIGNvdXJzZSBoYXMgaXRzIG93biBwYWdlIG9uIEdpdEh1YiwgeW91IGNhbiBmaW5kIGl0IGhlcmU6IFtodHRwczovL2dpdGh1Yi5jb20vdW5pLW1hbm5oZWltLXFtLTIwMjJdKGh0dHBzOi8vZ2l0aHViLmNvbS91bmktbWFubmhlaW0tcW0tMjAyMikuIFRoaXMgaXMgdGhlIHBsYWNlIHdoZXJlIHlvdSBjYW4gZmluZCBhbGwgcmVsZXZhbnQgbWF0ZXJpYWwgZm9yIHRoZSBsYWIgc2Vzc2lvbnMuIEl0IGlzIGFsc28gdGhlIHBsYWNlIHdoZXJlIHlvdSBkb3dubG9hZCBhbmQgaGFuZCBpbiB5b3VyIGhvbWV3b3JrIGFzc2lnbm1lbnRzLiAKClNvIGhvdyBkb2VzIHRoaXMgd29yaz8KCiMjIyMgR2V0IHRoZSBVUkwgb2YgdGhlIHJlcG8gZm9yIHRoZSBjdXJyZW50IHdlZWsKCkdvIHRvIFtodHRwczovL2dpdGh1Yi5jb20vdW5pLW1hbm5oZWltLXFtLTIwMjJdKGh0dHBzOi8vZ2l0aHViLmNvbS91bmktbWFubmhlaW0tcW0tMjAyMikgYW5kIGNsaWNrIG9uIHRoZSByZXBvc2l0b3J5IGZvciB0aGUgY3VycmVudCB3ZWVrICh0aGlzIHdlZWssIHRoaXMgaXMgY2FsbGVkIGB3ZWVrMDFfaW50cm9kdWN0aW9uYCkuIE5vdywgY2xpY2sgb24gdGhlIGdyZWVuICoqQ2xvbmUgb3IgZG93bmxvYWQqKiBidXR0b24gYW5kIHNlbGVjdCAqKlVzZSBIVFRQUyoqICh0aGlzIG1pZ2h0IGFscmVhZHkgYmUgc2VsZWN0ZWQgYnkgZGVmYXVsdCwgYW5kIGlmIGl0IGlzLCB5b3UnbGwgc2VlIHRoZSB0ZXh0IENsb25lIHdpdGggSFRUUFMgYXMgaW4gdGhlIGltYWdlIGJlbG93KS4gQ2xpY2sgb24gdGhlIGNsaXBib2FyZCBpY29uIHRvIGNvcHkgdGhlIHJlcG8gVVJMLgoKYGBge3IgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI0MCUiLCBmaWcuYWxpZ24gPSAnY2VudGVyJ30Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImltYWdlcy9naXRodWJfY2xvbmUucG5nIikKYGBgCgojIyMjIEltcG9ydCB0aGUgcmVwb3NpdG9yeSBpbiBSU3R1ZGlvCgogIDEuIE9wZW4gUlN0dWRpby4KICAyLiBDbGljayBvbiBgRmlsZWAgb24gdGhlIHRvcCBiYXIgYW5kIHNlbGVjdCBgTmV3IFByb2plY3QuLi5gLgoKYGBge3IgZWNobz1GQUxTRSwgb3V0LndpZHRoPSIxMDAlIiwgZmlnLmFsaWduID0gJ2NlbnRlcid9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvbmV3X3Byb2plY3QucG5nIikKYGBgCgogIDMuIFNlbGVjdCBgVmVyc2lvbiBDb250cm9sYC4gCiAgNC4gSW4gdGhlIG5leHQgd2luZG93LCBzZWxlY3QgYEdpdGAuCiAgNS4gSW4gdGhlIGZpbmFsIHdpbmRvdywgcGFzdGUgdGhlIHJlcG8gVVJMIHlvdSBncmFiYmVkIGZyb20gR2l0SHViIGluIHRoZSBgUmVwb3NpdG9yeSBVUkxgIHdpbmRvdy4gQ2xpY2sgb24gYEJyb3dzZWAgdG8gc2VsZWN0IHRoZSBmb2xkZXIgb24geW91ciBjb21wdXRlciB3aGVyZSB5b3Ugd2FudCB0byBzdG9yZSB0aGUgcHJvamVjdC4KICA2LiBDbGljayBvbiBgQ3JlYXRlIFByb2plY3RgLgogIAojIyMjIEdldCB3b3JraW5nCiAgNy4gT3BlbiB0aGUgYC5SbWRgIGZpbGUgdGhhdCBpcyBzdG9yZWQgaW4gdGhlIHByb2plY3QgKGluIHdlZWsgMSwgdGhpcyBpcyBjYWxsZWQgYFFNMjAyMl9XZWVrMDEuUm1kYCkuCgoKIyMgVGhlIFJTdHVkaW8gaW50ZXJmYWNlCgpUaGUgUlN0dWRpbyBpbnRlcmZhY2UgaGFzIGZvdXIgcGFuZXM6CgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSIxMDAlIiwgZmlnLmFsaWduID0gJ2NlbnRlcid9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJpbWFnZXMvcnN0dWRpb19pbnRlcmZhY2UucG5nIikKYGBgCgogIC0gKipFZGl0b3IqKjogVGhpcyBpcyB3ZXJlIHlvdSB1c3VhbGx5IGNvZGUuIFlvdSBjYW4gZWl0aGVyIHVzZSAuUm1kIChSIE1hcmtkb3duKSBvciAuUiAocGxhaW4gUiBjb2RlKSBmaWxlcy4KICAtICoqQ29uc29sZSoqOiBUaGlzIGlzIHdoZXJlIHRoZSByZXN1bHRzIGFwcGVhciBvbmNlIHlvdSBleGVjdXRlIHlvdXIgUi1jb2RlLiBZb3UgY2FuIGFsc28gZGlyZWN0bHkgdHlwZSBSLWNvZGUgaW50byB0aGUgY29uc29sZSBhbmQgZXhlY3V0ZSBpdC4gSG93ZXZlciwgd2UgY2Fubm90IHNhdmUgdGhpcyBjb2RlIHdoaWNoIGlzIHdoeSB3ZSB1c3VhbGx5IHdvcmsgaW4gdGhlIEVkaXRvci4KICAtICoqRW52aXJvbm1lbnQqKjogSGVyZSB5b3UgaGF2ZSBhbiBvdmVydmlldyBvdmVyIGFsbCB0aGUgb2JqZWN0cyBjdXJyZW50bHkgbG9hZGVkIGluIHlvdXIgZW52aXJvbm1lbnQuIFlvdSB3aWxsIGxlYXJuIG1vcmUgYWJvdXQgb2JqZWN0cyBsYXRlciBpbiB0aGUgY291cnNlLgogIC0gKipGaWxlcywgUGxvdHMsIFBhY2thZ2VzLCBIZWxwLCBWaWV3ZXIqKjogUGxvdHMgYW5kIG90aGVyIHRoaW5ncyB3aWxsIGFwcGVhciBoZXJlLCBkb24ndCB3b3JyeSB0b28gbXVjaCBhYm91dCBpdCBmb3IgdGhlIG1vbWVudC4KCgojIyBSIGFzIGEgYmFzaWMgY2FsY3VsYXRvcgoKRW5vdWdoIHByZXBhcmF0aW9uLCBsZXQncyBmaW5hbGx5IGRpdmUgaW50byBSIQoKUiBjYW4gcGVyZm9ybSBiYXNpYyBtYXRoIG9wZXJhdGlvbnMuIEhlcmUgYXJlIHNvbWUgZXhhbXBsZXM6CgpgYGB7ciBDYWxjdWxhdG9yfQoxICsgMQpgYGAKClNvbWUgbW9yZSBjYWxjdWxhdGlvbnM6CgpgYGB7ciBDYWxjdWxhdG9yMn0KMiAtIDMKCjQgKiA1CgoyXjIKCjQgLyAyCgoyXigxIC8gMikKYGBgCgpJZiB5b3UgcGxhY2UgcGFyZW50aGVzZXMgY29ycmVjdGx5LCBSIGluY29ycG9yYXRlcyB0aGUgb3JkZXIgb2Ygb3BlcmF0aW9ucy4KCmBgYHtyIENhbGN1bGF0b3IzfQooKDIgKyAyKSAqIDIpXjIKYGBgCgpUaGlzIHNob3VsZCBnaXZlIHRoZSBzYW1lIHJlc3VsdCBhcyBiZWZvcmUuCgpgYGB7ciBDYWxjdWxhdG9yNH0KKDQgKiAyKV4yCmBgYAoKCkJ1dCB0aGlzIG9mIGNvdXJzZSBnaXZlcyBhIGRpZmZlcmVudCByZXN1bHQ6CgpgYGB7ciBDYWxjdWxhdG9yNX0KKDIgKyAyICogMileMgpgYGAKICAgIApZb3UgY2FuIGFsc28gdXNlIG90aGVyIG1hdGggZnVuY3Rpb25zIHlvdSBrbm93IGZyb20geW91ciBjYWxjdWxhdG9yOgoKdGhpcyBpcyAkXHNxcnR7Mn0kCgpgYGB7ciBzcXJ0fQpzcXJ0KDIpCmBgYAoKd2hlbiB5b3UgZG8gbm90IHNwZWNpZnkgdGhlIGJhc2UsIFIgdXNlcyB0aGUgbmF0dXJhbCBsb2cgd2l0aCBiYXNlICRlJCwgaS5lLiAkXGxvZ19lKDEwKSQKCmBgYHtyIGxvZzF9CmxvZygxMCkKYGBgCgpidXQgUiBjYW4gYWxzbyB1c2UgYSBkaWZmZXJlbnQgKHZpcnR1YWxseSBhbnkpIGJhc2UsIGUuZy4gJFxsb2dfezEwfSgxMCkkCgpgYGB7ciBsb2cyLCBleGVyY2lzZT1UUlVFfQpsb2coMTAsIGJhc2UgPSAxMCkKYGBgCgpvciB3aXRoIGJhc2UgPSA1LCBpLmUuICRcbG9nXzUoMTApJAoKYGBge3IgbG9nM30KbG9nKDEwLCA1KQpgYGAKCgo+IDxpIGNsYXNzPSJmYSBmYS1ncmFkdWF0aW9uLWNhcCI+PC9pPiAqKlBybyB0aXA6KiogQWx3YXlzIGNsb3NlIHlvdXIgcGFyZW50aGVzZXMhIAoKCiAgLSBJZiB5b3UgZW5jb3VudGVyIGFuIGVycm9yIHdoZW4gcnVubmluZyB5b3VyIGNvZGUsIGl0IGlzIG9mdGVuIGEgbWlzc2luZyBwYXJlbnRoZXNpcywgYnJhY2Ugb3IgYnJhY2tldC4KICAtIFJTdHVkaW8gaGlnaGxpZ2h0cyB5b3VyIHBhaXJlZCBwYXJlbnRoZXNpcy4gVGhpcyBpcyByZWFsbHkgbmljZSBhbmQgaGVscGZ1bCEKCgojIyBNYWtlIHVzZSBvZiBjb21tZW50cwoKSXQgaXMgaGFyZCB0byB1bmRlcnN0YW5kIHB1cmUgY29kZSwgZXNwZWNpYWxseSBmb3Igc29tZW9uZSB3aG8gZGlkIG5vdCB3cml0ZSBpdCAoYW5kIGZ1dHVyZS15b3Ugd2lsbCBhbHNvIGhhdmUgYSBoYXJkIHRpbWUgdG8gdW5kZXJzdGFuZCBpdCkuCgoKPiA8aSBjbGFzcz0iZmEgZmEtZ3JhZHVhdGlvbi1jYXAiPjwvaT4gKipQcm8gdGlwOioqIEFkZCBjb21tZW50cyB0byB5b3VyIGNvZGUsIGRlc2NyaWJpbmcgd2hhdCB5b3UgYXJlIGRvaW5nIGFuZCB3aHkgeW91IGFyZSBkb2luZyBpdC4KCiAKKipXaXRoIGNvbW1lbnRzOioqCgotIE90aGVyIHBlb3BsZSBjYW4gdW5kZXJzdGFuZCB5b3VyIGNvZGUgKGZvciBleGFtcGxlIHVzIHdoZW4gd2UgYXJlIGdvaW5nIHRocm91Z2ggeW91ciBIb21ld29yayBhc3NpZ25tZW50cyBvciB5b3VyIGNsYXNzbWF0ZXMgd2hlbiB5b3UgYXJlIHRhbGtpbmcgYWJvdXQgeW91ciB3b3JrKS4KLSBZb3UgY2FuIHJlbWVtYmVyIHdoYXQgeW91IHdlcmUgZG9pbmcgd2hlbiB5b3UgcmVvcGVuIHlvdXIgY29kZSBhZnRlciB3ZWVrcyAoZS5nLiwgdG8gcHJlcGFyZSB0aGUgZGF0YSBlc3NheSBhdCB0aGUgZW5kIG9mIHRoZSBzZW1lc3RlcikuCgojIyMgU28gaG93IGNhbiBJIGFkZCBjb21tZW50cz8KCi0gQmVnaW4gYSBsaW5lIHdpdGggYSBgI2Agc3ltYm9sLCAKLSBFdmVyeXRoaW5nIG9uIHRoYXQgbGluZSBhZnRlciB0aGUgYCNgIHdpbGwgYmUgY29tbWVudGVkIG91dC4KLSBUaGlzIG1lYW5zIGlmIHlvdSBzZW5kIHRoZSBzY3JpcHQgdG8gdGhlIFIgY29uc29sZSB0aGUgY29uc29sZSB3aWxsIG5vdCBydW4gdGhlc2UgbGluZXMuIAoKYGBge3IgYWRkaXRpb259CiMgdGhpcyBpcyBhIGNvbW1lbnQKCjEgKyAxICMgVGhpcyBsaW5lIHJ1bnMKCiMgMSArIDEgVGhpcyBsaW5lIGRvZXMgbm90IHJ1bgpgYGAKCi0gSW5kZW50IHlvdXIgc2NyaXB0cyAoYm90aCBjb2RlIGFuZCBjb21tZW50cykgdXNpbmcgc3BhY2VzIHNvIHRoYXQgdGhleSBhcmUgcmVhZGFibGUuCi0gVHJ5IHRvIGNvZGUgYWNjb3JkaW5nIHRvIFtHb29nbGUncyBSIFN0eWxlIEd1aWRlXShodHRwOi8vYWR2LXIuaGFkLmNvLm56L1N0eWxlLmh0bWwpLgoKPiA8aSBjbGFzcz0iZmFzIGZhLXF1b3RlLXJpZ2h0Ij48L2k+IEdvb2QgY29kaW5nIHN0eWxlIGlzIGxpa2UgdXNpbmcgY29ycmVjdCBwdW5jdHVhdGlvbi4gPGJyPiBZb3VjYW5tYW5hZ2V3aXRob3V0aXRidXRpdHN1cmVtYWtlc3RoaW5nc2Vhc2llcnRvcmVhZC4uIC0tIEhhZGxleSBXaWNraGFtCgoKIyMgT2JqZWN0cyBpbiBSCgpCdXQgSSBhbHJlYWR5IGRvIGhhdmUgYSBjYWxjdWxhdG9yLiBXaHkgZG8gSSBuZWVkIFI/IAogIAo+IDxpIGNsYXNzPSJmYSBmYS1oYW5kLW8tcmlnaHQiPjwvaT4gUiBpcyBzbyBtdWNoIG1vcmUhIFIgaXMgYW4gb2JqZWN0LW9yaWVudGVkIHByb2dyYW1taW5nIGxhbmd1YWdlLgoKIyMjIyBXaGF0IGlzIGFuICJvYmplY3QiIGluIFI/CiAgCiAgLSBBbiBvYmplY3QgaXMgYSBmb3JtIHRvIHN0b3JlIHRoZSBkYXRhIHlvdSB3YW50IHRvIHVzZS4KCiMjIyMgV2hhdCBraW5kIG9mIGRhdGEgY2FuIEkgc3RvcmUgYXMgYW4gb2JqZWN0PwogICAgCiAgLSBJbiBSIHRoZXJlIGFyZSB0aHJlZSBtYWluIHR5cGVzIG9mIGRhdGEgeW91IGNhbiBzdG9yZToKICAgICAgLSBOdW1lcmljIChudW1iZXJzKQogICAgICAtIENoYXJhY3RlciAobGV0dGVycy93b3Jkcy9zZW50ZW5jZXMvdGV4dHMsIGNhbGxlZCBzdHJpbmdzKQogICAgICAtIExvZ2ljYWwgKFRSVUUvRkFMU0Ugc3RhdGVtZW50cykKICAtIFRoZXNlIGFyZSB0aGUgdHlwZXMgeW91IHdpbGwgb2Z0ZW4gZW5jb3VudGVyLgogIC0gSG93ZXZlciwgdGhlcmUgYXJlIG1hbnkgb3RoZXIgcG9zc2libGUgdHlwZXMuCgojIyMjIFNvIGhvdyBjYW4gSSBnZXQgaW5mb3JtYXRpb24gaW50byBhbiBvYmplY3Q/CiAgCiAgLSBTdG9yZSBhbiBvYmplY3QgYnkgdXNpbmcgYDwtYCBhcyBhc3NpZ25tZW50IG9wZXJhdG9yCgoqKkV4YW1wbGVzOioqCgpgYGB7ciBhc3NpZ25tZW50X29wZXJhdG9yLCBldmFsID0gVFJVRSwgZXJyb3I9VFJVRX0KbHVja3lfbnVtYmVyIDwtIDcKIAojIE5vdyB3ZSBjcmVhdGVkIGFuIChudW1lcmljKSBvYmplY3QgY2FsbGVkICJsdWNreV9udW1iZXIiCgpsdWNreV9udW1iZXIKYGBgCgpUaGUgYGNsYXNzKClgIGNvbW1hbmQgbGV0cyB1cyBjaGVjayB0aGUgdHlwZSBvZiBhbiBvYmplY3Q6CgpgYGB7ciBjbGFzc19jb21tYW5kLCBldmFsID0gVFJVRSwgZXJyb3I9VFJVRX0KbHVja3lfbnVtYmVyIDwtCgpjbGFzcyhsdWNreV9udW1iZXIpCmBgYAoKTGV0J3Mgc2VlIGhvdyB0aGlzIHdvcmtzIGxpdmUsIHRoaXMgdGltZSB3aXRoIGEgY2hhcmFjdGVyIG9iamVjdDoKCmBgYHtyIGNoYXJhY3Rlcl9vYmplY3QsIGV2YWwgPSBUUlVFLCBlcnJvcj1UUlVFfQpmaXJzdG5hbWUgPC0gIiIgIyBUaGlzIGlzIGEgY2hhcmFjdGVyIG9iamVjdAoKZmlyc3RuYW1lCgpjbGFzcyhmaXJzdG5hbWUpCgpsYXN0bmFtZSA8LSAiIgoKbGFzdG5hbWUKYGBgCgoKIyMjIEV4ZXJjaXNlIEk6IENyZWF0aW5nIG9iamVjdHMKCllvdXIgdHVybjogSGVyZSBpcyB5b3VyIHZlcnkgZmlyc3QgZXhlcmNpc2UhIAoKPiAgPGkgY2xhc3M9ImZhIGZhLWdyYWR1YXRpb24tY2FwIj48L2k+IFBybyB0aXA6IENvcHkgdGhlIGxpbmVzIG9mIGNvZGUgdGhhdCB3b3JrZWQgZm9yIHNvbWV0aGluZyBzaW1pbGFyLiBUaGVuLCBhZGp1c3QgdGhlIGNvZGUgYWNjb3JkaW5nIHRvIHlvdXIgcHJvYmxlbS4gVGhhdCdzIGhvdyBjb2Rpbmcgd29ya3MgbW9zdCBvZiB0aGUgdGltZSEKCkNyZWF0ZSB0aHJlZSBvYmplY3RzOgoKICAgIDEuIGBteV9sdWNreV9udW1iZXJgIHNob3VsZCBjb250YWluIHlvdXIgbHVja3kgbnVtYmVyLgogICAgMi4gYG15X2ZpcnN0bmFtZWAgc2hvdWxkIGNvbnRhaW4geW91ciBmaXJzdG5hbWUuCiAgICAzLiBgbXlfbGFzdG5hbWVgIHNob3VsZCBjb250YWluIHlvdXIgbGFzdG5hbWUuCgpBZnRlciB5b3UgY3JlYXRlZCB0aGUgb2JqZWN0cywgY2FsbCB0aGVtIHNlcGFyYXRlbHkuIERvbid0IGZvcmdldCB0byBhZGQgY29tbWVudHMgdG8geW91ciBjb2RlLgoKYGBge3IgRXhlcmNpc2VfSV8xLCBldmFsID0gVCwgZXJyb3I9VFJVRX0KbXlfbHVja3lfbnVtYmVyIDwtIDIzICMgVGhpcyBpcyBteSBsdWNreSBudW1iZXIKbXlfZmlyc3RuYW1lIDwtICJPbGl2ZXIiICMgVGhpcyBpcyBteSBmaXJzdCBuYW1lCm15X2xhc3RuYW1lIDwtICJSaXR0bWFubiIgIyBUaGlzIGlzIG15IGxhc3QgbmFtZQoKIyBoZXJlLCBJIGNhbGwgdGhlIG5ldyBvYmplY3RzCm15X2x1Y2t5X251bWJlcgpteV9maXJzdG5hbWUKbXlfbGFzdG5hbWUKYGBgCgoKCiMjIERhdGEgU3RydWN0dXJlcwoKV2hhdCBraW5kIG9mIGRhdGEgY2FuIEkgc3RvcmUgaW4gUj8gRGlmZmVyZW50IHR5cGVzIG9mIG9iamVjdHMgdGhhdCBjYW4gY29udGFpbiBkaWZmZXJlbnQgdHlwZXMgYW5kIHNldHMgb2YgZGF0YToKCiAgLSAqKlNjYWxhcioqOiAgICAgIG51bWJlcnMsIGNoYXJhY3RlcnMsIGxvZ2ljYWwgdmFsdWVzCiAgLSAqKlZlY3RvcioqOiAgICAgIHNldHMgb2Ygc2NhbGFycyAodGh1cywgbnVtYmVycywgY2hhcmFjdGVycywgbG9naWNhbCkKICAtICoqTWF0cml4Kio6ICAgICAgdHdvLWRpbWVuc2lvbmFsIHNldCBvZiBzY2FsYXJzIG9mIHNhbWUgdHlwZQogIC0gKipEYXRhIGZyYW1lKio6ICBjb2xsZWN0aW9ucyBvZiB2ZWN0b3JzIG9mIChwb3NzaWJseSkgZGlmZmVyZW50IHR5cGVzCiAgLSAqKkFycmF5Kio6ICAgICAgIG11bHRpZGltZW5zaW9uYWwgc2V0IG9mIHNjYWxhcnMgb2Ygc2FtZSB0eXBlCiAgLSAqKkxpc3QqKjogICAgICAgIGNvbWJpbmF0aW9ucyBvZiBzY2FsYXJzLCB2ZWN0b3JzLCBtYXRyaWNlcy4uLgoKV2Ugd2lsbCBnbyB0aHJvdWdoIGFsbCBvZiB0aGVzZSBvYmplY3QgdHlwZXMgYmVsb3cuIE9uIHRvcCBvZiB0aGF0IHdlIHdpbGwgYWxzbyBsZWFybiBob3cgdG8gY2FsY3VsYXRlIHRoZSBtZWFzdXJlcyBvZiBjZW50cmFsIHRlbmRlbmN5IGFuZCB2YXJpYWJpbGl0eSB3aXRoIHZlY3RvcnMuCgoKIyMjIERhdGEgU3RydWN0dXJlcyAtIFZlY3RvcnMKCkxldCdzIHN0YXJ0IHdpdGggdmVjdG9ycy4gV2Ugd2FudCBhIHZlY3RvciBvZiB0aGUgbnVtYmVycyAxLCAyLCAzLCA0IGFuZCA1LiBIb3cgZG8gSSBhc3NpZ24gdGhpcyBzZXQgb2YgbnVtYmVycyB0byBhIHZlY3Rvcj8KCjxpIGNsYXNzPSJmYSBmYS1oYW5kLW8tcmlnaHQiPjwvaT4gVGhlIGBjKClgIGZ1bmN0aW9uIGNvbWJpbmVzIHNpbmdsZSB2YWx1ZXMgdG8gYSB2ZWN0b3I6CgpgYGB7ciB2ZWN9CmV4YW1wbGVfdmVjIDwtIGMoMSwgMiwgMywgNCwgNSkKCmV4YW1wbGVfdmVjCmBgYAoKVGhpcyBhbHNvIHdvcmtzIGZvciBjaGFyYWN0ZXJzL3N0cmluZ3M6CgpgYGB7ciBjaGFyX3ZlY30KY291bnRyeV9jb2RlIDwtIGMoIkRFIiwgIkZSIiwgIk5MIiwgIlVTIiwgIlVLIikKCmNvdW50cnlfY29kZQpgYGAKCkFuZCBpdCBhbHNvIHdvcmtzIGZvciBhIGNvbWJpbmF0aW9uIG9mIG51bWJlcnMgYW5kIGNoYXJhY3RlcnM6CgpgYGB7ciBjb21iaTF9CmV4YW1wbGVfdmVjMiA8LSBjKCJXZWxjb21lIiwgInRvIiwgInRoZSIsICJsYWIiLCAiaW4iLCAiQSIsIDUpCgpleGFtcGxlX3ZlYzIKYGBgCgpXaGF0IGlmIHdlIHN0YXJ0IHdpdGggbnVtYmVycz8KCmBgYHtyIGNvbWJpMn0KZXhhbXBsZV92ZWMzIDwtIGMoMSwgMiwgMywgNCwgNSwgIlIgY2FuIGNvdW50ISIpCgpleGFtcGxlX3ZlYzMKYGBgCgoKPGkgY2xhc3M9ImZhIGZhLWhhbmQtby1yaWdodCI+PC9pPiBOb3RlIHRoYXQgaWYgeW91IGhhdmUgYSBjaGFyYWN0ZXIgZmllbGQgaW4geW91ciB2ZWN0b3IsIFIgd2lsbCB0dXJuIEFMTCB2YWx1ZXMgaW50byBjaGFyYWN0ZXIgZGF0YSEgKFlvdSBjYW4gc2VlIHRoYXQgYnkgdGhlIHF1b3RlcyBhcm91bmQgdGhlIHZhbHVlcykKCkxldCdzIGNoZWNrIHRoZSB0eXBlIG9mIGRhdGEgYnkgdXNpbmcgdGhlIGBjbGFzcygpYCBjb21tYW5kIG9uIGBleGFtcGxlX3ZlYzNgLgoKYGBge3IgY29tYmkzfQpleGFtcGxlX3ZlYzMgPC0gYygxLCAyLCAzLCA0LCA1LCAiUiBjYW4gY291bnQhIikKCmNsYXNzKGV4YW1wbGVfdmVjMykKYGBgCgpZb3UgY2FuIHVzZSBtYXRoZW1hdGljYWwgZnVuY3Rpb25zIG9uIGVhY2ggZWxlbWVudCBpbiBudW1lcmljIHZlY3RvcnMvbWF0cmljZXMgZXRjLgoKYGBge3IgZnVuY3Rpb25zX29iamVjdHMxfQpleGFtcGxlX3ZlYyA8LSBjKDEsIDIsIDMsIDQsIDUpCgpzcXJ0KGV4YW1wbGVfdmVjKSAjIFRha2UgdGhlIHNxdWFyZSByb290IG9mIGVhY2ggZWxlbWVudCBpbiBleGFtcGxlX3ZlYwpgYGAKCldoYXQgYWJvdXQgbXVsdGlwbGljYXRpb24/CgpgYGB7ciBmdW5jdGlvbnNfb2JqZWN0czN9CmV4YW1wbGVfdmVjIDwtIGMoMSwgMiwgMywgNCwgNSkKCmV4YW1wbGVfdmVjICogMTAKYGBgCgpUaGVyZSBhcmUgYWxzbyBzb21lIGZ1bmN0aW9ucyB0aGF0IHlvdSBjYW4gdXNlIG9uIHRoZSB3aG9sZSB2ZWN0b3IuCgpgYGB7ciBmdW5jdGlvbnNfb2JqZWN0czR9CmV4YW1wbGVfdmVjIDwtIGMoMSwgMiwgMywgNCwgNSkKCnN1bShleGFtcGxlX3ZlYykgIyBRdWVzdGlvbjogV2hhdCBkb2VzIHN1bSgpIGRvPwoKbGVuZ3RoKGV4YW1wbGVfdmVjKSAjIFF1ZXN0aW9uOiBXaGF0IGRvZXMgbGVuZ3RoKCkgZG8/CmBgYAoKCiMjIyBEYXRhIFN0cnVjdHVyZXMgLSBNYXRyaWNlcwoKPGkgY2xhc3M9ImZhIGZhLWhhbmQtby1yaWdodCI+PC9pPiBNYXRyaWNlcyBpbiBSIGFyZSB0d28tZGltZW5zaW9uYWwgdGFibGUgb2JqZWN0cy4gSW4gUiwgbWF0cmljZXMgYXJlIGFsd2F5cyByb3cgYnkgY29sdW1uLiBMaWtlICoqcioqb2xsZXIgKipjKipvYXN0ZXIsICoqUioqb21hbiAqKkMqKmF0aG9saWMgb3IgKipSKipheSAqKkMqKmhhcmxlcykuCgpJbiBhIG1hdHJpeCwgYWxsIGRhdGEgbXVzdCBiZSBvZiB0aGUgc2FtZSB0eXBlLiBJZiB5b3UgbWl4IG51bWVyaWMgYW5kIGNoYXJhY3RlciBlbnRyaWVzLCB0aGUgbWF0cml4IHdpbGwgYmUgYWxsIGNoYXJhY3RlciBqdXN0IGxpa2UgaW4gYSB2ZWN0b3IuCgpIb3cgZG8gSSBjcmVhdGUgYSBtYXRyaXggaW4gUj8KCmBgYHtyIG1hdDF9CmV4YW1wbGVfbWF0MSA8LSBtYXRyaXgoYygxLCAyLCAzLCA0LCA1LCA2KSwKICBucm93ID0gMywKICBuY29sID0gMgopCgpleGFtcGxlX21hdDEgIyBIb3cgZGlkIFIgZmlsbCB0aGUgbnVtYmVycyBpbiB0aGUgbWF0cml4PwpgYGAKCllvdSBjb3VsZCBhbHNvIGNoYW5nZSB0aGUgb3B0aW9ucyBhbiBsZXQgUiBmaWxsIHRoZSBtYXRyaXggKmJ5IHJvd3MqIChpbnN0ZWFkIG9mIGNvbHVtbnMpOgoKYGBge3IgbWF0Mn0KZXhhbXBsZV9tYXQyIDwtIG1hdHJpeChjKDEsIDIsIDMsIDQsIDUsIDYpLAogIG5yb3cgPSAzLAogIG5jb2wgPSAyLAogIGJ5cm93ID0gVAopCgpleGFtcGxlX21hdDIgIyBTZWUgdGhlIGRpZmZlcmVuY2U/CmBgYAoKCk9yIHlvdSBjb3VsZCBjcmVhdGUgYSBtYXRyaXggZnJvbSBkaWZmZXJlbnQgdmVjdG9ycyBieSB1c2luZyBjb2x1bW4tYmluZCBvbiB0d28gb3IgbW9yZSB2ZWN0b3JzLiBJdCB3b3JrcyBzaW1pbGFyIHRvIHRoZSBgYygpYCBmdW5jdGlvbiBidXQgd2l0aCB2ZWN0b3JzIGFzIGlucHV0IGluc3RlYWQgb2Ygc2NhbGFycy4KCkxldCdzIGZpcnN0IGNyZWF0ZSB0d28gdmVjdG9ycyBvZiB0aGUgc2FtZSBsZW5ndGg6CgpgYGB7ciBtYXQzfQp2ZWMxIDwtIGMoMSwgMiwgMywgNCwgNSwgNikKCnZlYzIgPC0gYyg3LCA4LCA5LCAxMCwgMTEsIDEyKQoKIyBBbmQgbm93IGNvbHVtbi1iaW5kIC0gY2JpbmQoKSAtIHRoZSB0d28gdmVjdG9ycy4KCmV4YW1wbGVfbWF0MyA8LSBjYmluZCh2ZWMxLCB2ZWMyKQoKZXhhbXBsZV9tYXQzCmBgYAoKU2ltaWxhcmx5LCB3ZSBjYW4gcm93LWJpbmQgLS0gYHJiaW5kKClgIC0tIHRoZSB0d28gdmVjdG9yczoKCmBgYHtyIG1hdDR9CnZlYzEgPC0gYygxLCAyLCAzLCA0LCA1LCA2KQoKdmVjMiA8LSBjKDcsIDgsIDksIDEwLCAxMSwgMTIpCgpleGFtcGxlX21hdDQgPC0gcmJpbmQodmVjMSwgdmVjMikKCmV4YW1wbGVfbWF0NApgYGAKCiMjIyBEYXRhIFN0cnVjdHVyZXMgLSBEYXRhIGZyYW1lcwoKPGkgY2xhc3M9ImZhIGZhLWhhbmQtby1yaWdodCI+PC9pPiBEYXRhIGZyYW1lcyBhcmUgdHdvLWRpbWVuc2lvbmFsIHRhYmxlIG9iamVjdHMsIGp1c3QgbGlrZSBtYXRyaWNlcy4gTW9zdCBkYXRhIHlvdSB3aWxsIGFuYWx5emUgaW4gUiB3aWxsIGJlIGluIHRoaXMgZm9ybS4KCllvdSBjYW4gY3JlYXRlIGRhdGEgZnJhbWVzIGZyb20gdmVjdG9ycyBqdXN0IGxpa2UgYGNiaW5kKClgIHVzaW5nIGBkYXRhLmZyYW1lKClgOgoKYGBge3IgZGYwMX0KdmVjMSA8LSBjKDEsIDIsIDMsIDQsIDUsIDYpCgp2ZWMyIDwtIGMoNywgOCwgOSwgMTAsIDExLCAxMikKCmV4YW1wbGVfZGYxIDwtIGRhdGEuZnJhbWUodmVjMSwgdmVjMikKCmV4YW1wbGVfZGYxCmBgYAoKSG93ZXZlciwgZGF0YSBmcmFtZXMgYXJlIGFsd2F5cyBjb2x1bW4tYm91bmQgdmVjdG9ycy4gSW4gYSBkYXRhIGZyYW1lLCBldmVyeXRoaW5nIHdpdGhpbiBhIGNvbHVtbiBoYXMgdG8gYmUgb2YgdGhlIHNhbWUgZGF0YSB0eXBlLiBCdXQgKip5b3UgY2FuIG1peCBkYXRhIHR5cGVzIGJldHdlZW4gY29sdW1ucyoqOiAKCmBgYHtyIGRmMDJ9CnZlYzEgPC0gYygxLCAyLCAzLCA0LCA1LCA2KQoKdmVjMiA8LSBjKDcsIDgsIDksIDEwLCAxMSwgMTIpCgp2ZWMzIDwtCiAgYygKICAgICJGaXJzdCBSb3ciLAogICAgIlNlY29uZCBSb3ciLAogICAgIlRoaXJkIFJvdyIsCiAgICAiRm91cnRoIFJvdyIsCiAgICAiRmlmdGggUm93IiwKICAgICJTaXh0aCBSb3ciCiAgKQoKZXhhbXBsZV9kZjIgPC0gZGF0YS5mcmFtZSh2ZWMxLCB2ZWMyLCB2ZWMzKQoKZXhhbXBsZV9kZjIKYGBgCgoKWW91IGNhbiBhbHNvIG5hbWUgeW91ciBjb2x1bW5zL3ZhcmlhYmxlcy4gRWl0aGVyIHdoZW4gY3JlYXRpbmcgeW91ciBkYXRhIGZyYW1lOgoKYGBge3IgZGYwM30KdmVjMSA8LSBjKDEsIDIsIDMsIDQsIDUsIDYpCgp2ZWMyIDwtIGMoNywgOCwgOSwgMTAsIDExLCAxMikKCnZlYzMgPC0KICBjKAogICAgIkZpcnN0IFJvdyIsCiAgICAiU2Vjb25kIFJvdyIsCiAgICAiVGhpcmQgUm93IiwKICAgICJGb3VydGggUm93IiwKICAgICJGaWZ0aCBSb3ciLAogICAgIlNpeHRoIFJvdyIKICApCgpleGFtcGxlX2RmMyA8LSBkYXRhLmZyYW1lKAogIHZhcmlhYmxlXzF0bzYgPSB2ZWMxLAogIHZhcmlhYmxlXzd0bzEyID0gdmVjMiwKICB2YXJpYWJsZV9yb3dzID0gdmVjMwopCgpleGFtcGxlX2RmMwpgYGAKCk9yIGJ5IHJlbmFtaW5nIGFuIGV4aXN0aW5nIGRhdGEgZnJhbWUuCgpgYGB7ciBkZjA0fQp2ZWMxIDwtIGMoMSwgMiwgMywgNCwgNSwgNikKCnZlYzIgPC0gYyg3LCA4LCA5LCAxMCwgMTEsIDEyKQoKdmVjMyA8LQogIGMoCiAgICAiRmlyc3QgUm93IiwKICAgICJTZWNvbmQgUm93IiwKICAgICJUaGlyZCBSb3ciLAogICAgIkZvdXJ0aCBSb3ciLAogICAgIkZpZnRoIFJvdyIsCiAgICAiU2l4dGggUm93IgogICkKCmV4YW1wbGVfZGYzIDwtIGRhdGEuZnJhbWUodmVjMSwgdmVjMiwgdmVjMykKCgojIFJlbmFtZSB0aGUgdmFyaWFibGVzIG9mIGFuIGV4aXN0aW5nIGRhdGEgZnJhbWUKCm5hbWVzKGV4YW1wbGVfZGYzKSA8LSBjKCJ2YXJpYWJsZS4xIiwgInZhcmlhYmxlLjIiLCAidmFyaWFibGUuMyIpCgpleGFtcGxlX2RmMwpgYGAKCmBgYHtyICJleGFtcGxlX2RmM19zZXR1cCJ9CnZlYzEgPC0gYygxLCAyLCAzLCA0LCA1LCA2KQoKdmVjMiA8LSBjKDcsIDgsIDksIDEwLCAxMSwgMTIpCgp2ZWMzIDwtCiAgYygKICAgICJGaXJzdCBSb3ciLAogICAgIlNlY29uZCBSb3ciLAogICAgIlRoaXJkIFJvdyIsCiAgICAiRm91cnRoIFJvdyIsCiAgICAiRmlmdGggUm93IiwKICAgICJTaXh0aCBSb3ciCiAgKQoKZXhhbXBsZV9kZjMgPC0gZGF0YS5mcmFtZSh2ZWMxLCB2ZWMyLCB2ZWMzKQoKbmFtZXMoZXhhbXBsZV9kZjMpIDwtIGMoInZhcmlhYmxlLjEiLCAidmFyaWFibGUuMiIsICJ2YXJpYWJsZS4zIikKYGBgCgoKV2UgY2FuIGFsc28gYWRkIGEgbmV3IHZhcmlhYmxlIHRvIGFuIGV4aXN0aW5nIGRhdGEgZnJhbWUuIFdlIHNpbXBseSBjcmVhdGUgYSBkYXRhIGZyYW1lIHdoaWNoIGNvbnNpc3RzIG9mIGEgZGF0YSBmcmFtZSBhbmQgYSB2ZWN0b3I6CgpgYGB7ciBkZjA1LCBleGVyY2lzZS5zZXR1cD0iZXhhbXBsZV9kZjNfc2V0dXAifQpleGFtcGxlX2RmNCA8LQogIGRhdGEuZnJhbWUoZXhhbXBsZV9kZjMsIAogICAgICAgICAgICAgdmFyaWFibGVfNCA9IGMoOTAsIDkxLCA5MiwgOTMsIDk0LCA5NSkpCgpleGFtcGxlX2RmNApgYGAKCgojIyMgRGF0YSBTdHJ1Y3R1cmVzIC0gQXJyYXlzCgpUaGVzZSBhcmUgbGlrZSBtYXRyaWNlcywgZXhjZXB0IHRoYXQgdGhleSBhcmUgdHlwaWNhbGx5IHRocmVlLWRpbWVuc2lvbmFsLiBZb3UncmUgbm90IGdvaW5nIHRvIHNlZSBtYW55IG9mIHRoZXNlLCBidXQgd2UnbGwgaW50cm9kdWNlIHRoZW0gZm9yIGNvbXBsZXRlbmVzcy4gSGVyZSBpcyBhbiBpbGx1c3RyYXRpb24gb2Ygd2hhdCBhIHRocmVlLWRpbWVuc2lvbmFsIGFycmF5IGNvdWxkIGxvb2sgbGlrZToKCiFbXShodHRwczovL3d3dy5tYXRod29ya3MuY29tL21hdGxhYmNlbnRyYWwvbWxjLWRvd25sb2Fkcy9kb3dubG9hZHMvZWUxNGM0NGQtNjA1Mi00ZDQzLWE4YjktN2JjNGRmNmI4Y2U0LzgxYzU0ZDZmLTU2ZWQtNDlkYi1hZjdmLTM5ZTZiNGRhNWFkZi9pbWFnZXMvc2NyZWVuc2hvdC5qcGcpCgpZb3UgY2FuIHRoaW5rIG9mIDEwIDMgeCA1IGJpbmdvIGNhcmRzLCB0aGF0IGFsbCBkaXNwbGF5IHNwYWNlcyAxIHRocm91Z2ggMTUgZm9yIGV4YW1wbGUsIGFzIGFuIGFycmF5LiBJZiBJIHdlcmUgdG8gZGlzcGxheSB0aGF0IGluIFIsIEkgd291bGQgdXNlIHRoZSBhcnJheSBmdW5jdGlvbiB0byB3cml0ZToKCmBgYHtyIGFycmF5LCByZXN1bHRzID0gImhpZGUifQpiaW5nb19hcnJheSA8LSBhcnJheShzZXEoMSwgMTUsIDEpLCAKICAgICAgICAgICAgICAgICAgICAgZGltID0gYygzLCA1LCAxMCkpCgpiaW5nb19hcnJheQpgYGAKClRoZSBnZW5lcmFsIHN5bnRheCBmb3IgdGhpcyBmdW5jdGlvbiBpcyBgYXJyYXkodmFsdWVzIHlvdSB3YW50IHRvIGFycmF5LCBkaW0gPSAocm93LCBjb2x1bW4sIGhlaWdodCkpYC4KCiMjIyBEYXRhIFN0cnVjdHVyZXMgLSBMaXN0cwoKTGlzdCBvYmplY3RzIGNhbiBjb250YWluIGEgc2VyaWVzIG9mIHRoZSBvdGhlciBvYmplY3RzIHdlIGp1c3QgbGVhcm5lZCBhYm91dC4gQSBzaW5nbGUgbGlzdCBjYW4gY29udGFpbiBhIHZhbHVlLCBhIHZlY3RvciwgYSBtYXRyaXgsIEFORCBhIGRhdGFmcmFtZSAtIG9yIG1hbnkgb2YgZWFjaCEKCkhvdyBkbyBJIG1ha2UgYSBsaXN0PwoKPGkgY2xhc3M9ImZhIGZhLWhhbmQtby1yaWdodCI+PC9pPiBVc2UgdGhlIGBsaXN0KClgIGZ1bmN0aW9uIQogICAgCmBgYHtyIGxpc3QsIHJlc3VsdHMgPSAiaGlkZSJ9CiMgY3JlYXRlIGEgdmVjdG9yCmV4YW1wbGVfdmVjIDwtIGMoMSwgMiwgMywgNCwgNSwgNiwgNywgOCkKCiMgY3JlYXRlIGEgbWF0cml4CmV4YW1wbGVfbWF0IDwtIG1hdHJpeChjKDEsIDIsIDMsIDQsIDUsIDYpLAogICAgICAgICAgICAgICAgICAgICAgbnJvdyA9IDMsCiAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMikKCiMgY3JlYXRlIGFuIGFycmF5CmV4YW1wbGVfYXJyYXkgPC0gYXJyYXkoc2VxKDEsIDE1LCAxKSwgZGltID0gYygzLCA1LCAxMCkpCgpleGFtcGxlX3ZlYzMgPC0gYygxLCAyLCAzLCA0KQoKCiMjIFN0b3JlIGFsbCBvYmplY3RzIGluIGEgbGlzdAoKZXhhbXBsZV9saXN0IDwtIGxpc3QoZXhhbXBsZV92ZWMsIGV4YW1wbGVfbWF0LCBleGFtcGxlX2FycmF5KQoKZXhhbXBsZV9saXN0CmBgYAoKIyMgU2VsZWN0aW5nIGVsZW1lbnRzIGluIGEgdmVjdG9yLCBtYXRyaXggb3IgZGF0YS5mcmFtZQoKU29tZXRpbWVzIHdlIHdhbnQgdG8gc2VsZWN0IHNpbmdsZSBvciBtdWx0aXBsZSBkYXRhIGVudHJpZXMgZnJvbSBvdXIgb2JqZWN0cy4gV2UgY2FuIGRvIHRoaXMgYnkgc2VsZWN0aW5nIGVsZW1lbnRzIHZpYSBgW11gLgoKTGV0J3MgZmlyc3QgZG8gaXQgd2l0aCBhIHZlY3Rvci4gUmVtZW1iZXIgb3VyIGNvdW50cnlfY29kZSB2ZWN0b3I/CgpgYGB7ciBzZWxlY3Rpb24xfQpjb3VudHJ5X2NvZGUgPC0gYygiREUiLCAiRlIiLCAiTkwiLCAiVVMiLCAiVUsiKQoKY291bnRyeV9jb2RlCmBgYAoKCmBgYHtyIGNvdW50cnlfY29kZV9zZXR1cH0KY291bnRyeV9jb2RlIDwtIGMoIkRFIiwgIkZSIiwgIk5MIiwgIlVTIiwgIlVLIikKYGBgCgoKTGV0J3Mgc2F5IHdlIG9ubHkgd2FudCB0byBzZWxlY3QgdGhlICJVUyIuIFdlIGNhbiBhY2hpZXZlIHRoaXMgYnkgYWNjZXNzaW5nIHRoZSB2YWx1ZSB2aWEgaXRzIHBvc2l0aW9uIGluIHRoZSB2ZWN0b3I6CgpgYGB7ciBzZWxlY3Rpb24yfQpjb3VudHJ5X2NvZGVbNF0KYGBgCgpOb3cgd2Ugd2FudCB0byBzZWxlY3QgYWxsIHZhbHVlcyBidXQgdGhlICJVUyI6CgpgYGB7ciBzZWxlY3Rpb24zfQpjb3VudHJ5X2NvZGVbLTRdCmBgYAoKWW91IGNhbiBwYXNzIG11bHRpcGxlIGluZGV4ZXMgYXMgYSB2ZWN0b3I6CgpgYGB7ciBzZWxlY3Rpb240fQpjb3VudHJ5X2NvZGVbYygxLCAyLCAzKV0KYGBgCgpgMTozYCBnZW5lcmF0ZXMgdGhlIHZlY3RvciBgYygxLCAyLCAzKWAgYSBiaXQgcXVpY2tlci4KCmBgYHtyIHNlbGVjdGlvbjV9CmNvdW50cnlfY29kZVsxOjNdCmBgYAoKCklmIHdlIHdhbnQgdGhlIHZhbHVlcyAiREUiLCAiRlIiLCBhbmQgIlVTIiwgYSBzZXF1ZW5jZSBkb2VzIG5vdCByZWFsbHkgaGVscC4gQnV0IHdlIGNhbiBwdXQgYSB2ZWN0b3Igd2l0aCBhIGNvbWJpbmF0aW9uIG9mIGEgc2VxdWVuY2UgYW5kIHNvbWUgb3RoZXIgdmFsdWVzIGluIHRoZSBzcXVhcmUgYnJhY2tldHM6CgpgYGB7ciBzZWxlY3Rpb242fQpjb3VudHJ5X2NvZGVbYygxOjIsIDQpXQpgYGAKCiMjIyMgU2VsZWN0aW5nIGl0ZW1zIGluIHR3by1kaW1lbnNpb25hbCBvYmplY3RzCgpXZSBjYW4gYWNjZXNzIHZhbHVlcyBvZiBhIG1hdHJpeCBzaW1pbGFybHkuIEhvd2V2ZXIsIHdlIG5lZWQgdG8gdGhpbmsgb2Ygb25lIGFkZGl0aW9uYWwgZGltZW5zaW9uLiAKCmBgYHtyIG1hdH0KZXhhbXBsZV9tYXQgPC0gbWF0cml4KGMoMSwgMiwgMywgNCwgNSwgNiksCiAgICAgICAgICAgICAgICAgICAgICBucm93ID0gMywKICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAyKQoKZXhhbXBsZV9tYXQKYGBgCgoKR2VuZXJhbGx5LCB3ZSB0eXBlIGBvYmplY3Rbcm93LCBjb2x1bW5dYCB0byBhY2Nlc3Mgc3BlY2lmaWMgcm93cyBhbmQgY29sdW1ucy4gVG8gc2VlIGhvdyB0aGlzIHdvcmtzLCBsZXQncyBoYXZlIGEgbG9vayBhdCBvdXIgYGV4YW1wbGVfbWF0YDoKCk5vdyB3ZSB3YW50IHRvIGFjY2VzcyB0aGUgdmFsdWUgNi4gSXQncyBpbiB0aGUgdGhpcmQgcm93IGFuZCB0aGUgc2Vjb25kIGNvbHVtbi4KCmBgYHtyIHNlbGVjdGlvbjd9CmV4YW1wbGVfbWF0WzMsIDJdCmBgYAoKV2UgY291bGQgYWxzbyBzZWxlY3QgYW4gZW50aXJlIGNvbHVtbiAoYW5kIHVzZSBpdCBsaWtlIGEgdmVjdG9yKS4KCmBgYHtyIHNlbGVjdGlvbjh9CmV4YW1wbGVfbWF0WywgMl0KYGBgCgoKQnkgYWNjZXNzaW5nIHZhbHVlcyB3aXRoIHRoZSBgW11gIHNxdWFyZSBicmFja2V0cywgd2UgY291bGQgYWxzbyByZXBsYWNlIHZhbHVlcy4gCkxldCdzIHNheSB3ZSB3YW50IHRvIHJlY29kZSB0aGUgZW50aXJlIGZpcnN0IGNvbHVtbiBpbiBgZXhhbXBsZV9tYXQzYCB0byA5OToKCmBgYHtyIHNlbGVjdGlvbjl9CmV4YW1wbGVfbWF0WywgMV0gPC0gOTkKCmV4YW1wbGVfbWF0CmBgYAoKYGBge3IgbWF0X3NldHVwMn0KZXhhbXBsZV9tYXQgPC0gbWF0cml4KGMoMSwgMiwgMywgNCwgNSwgNiksCiAgICAgICAgICAgICAgICAgICAgICBucm93ID0gMywKICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAyKQoKZXhhbXBsZV9tYXRbLCAxXSA8LSA5OQpgYGAKCgpgYGB7ciBzZWxlY3Rpb24xMH0KIyBBbmQgd2Ugd2FudCB0byByZWNvZGUgdGhlIGZpcnN0IGFuZCB0aGUgdGhpcmQgdmFsdWUgaW4gdGhlIHNlY29uZCBjb2x1bW4KIyB0byA5MSBhbmQgMTAwCgpleGFtcGxlX21hdFtjKDEsIDMpLCAyXSA8LSBjKDkxLCAxMDApCgpleGFtcGxlX21hdApgYGAKCgojIyMgU2VsZWN0aW9uIHdpdGggY29uZGl0aW9ucwoKVGhpcyBpcyBhIGdvb2Qgc3RhcnQgdG8gc2VsZWN0IGFuZCByZWNvZGUgZGF0YSBpbiBhbiBvYmplY3QuIApIb3dldmVyLCBpdCBtaWdodCBiZSBhIGJpdCBleGhhdXN0aW5nIChtYXliZSBldmVuIGltcG9zc2libGUpIHRvIGFsd2F5cyBsb29rIHVwIHRoZSBleGFjdCBwb3NpdGlvbiBpbiB0aGUgb2JqZWN0LgoKTHVja2lseSwgUiBsZXQncyB1cyBhbHNvIHNlbGVjdCBlbGVtZW50cyBiYXNlZCBvbiBjb25kaXRpb25zLiAKSW5zdGVhZCBvZiB0aGUgcG9zaXRpb24gd2UgcHV0IGEgY29uZGl0aW9uIGluIHRoZSBbXSBzcXVhcmUgYnJhY2tldHMuCgoKIC0gRm9yIHRoaXMgd2UgY2FuIHVzZSBzZXZlcmFsIGNvbmRpdGlvbnM6CiAgICAtIElzIGVxdWFsIHRvOiAgICAgICAgICAgIGA9PWAKICAgIC0gSXMgbm90OiAgICAgICAgICAgICAgICAgYCE9YAogICAgLSBJcyBzbWFsbGVyIHRoYW46ICAgICAgICBgPGAKICAgIC0gSXMgZ3JlYXRlciB0aGFuOiAgICAgICAgYD5gCiAgICAtIElzIHNtYWxsZXIgb3IgZXF1YWwgdG86IGA8PWAKICAgIC0gSXMgZ3JlYXRlciBvciBlcXVhbCB0bzogYD49YAoKIC0gQ29uZGl0aW9ucyBjYW4gYmUgY29tYmluZWQgd2l0aCBhbmQgYW5kL29yIG9yIHN0YXRlbWVudHMKICAgIC0gQU5EOiBgJmAKICAgIC0gT1I6ICBgfGAKICAgIApTbyBob3cgZG8gY29uZGl0aW9ucyB3b3JrPyBMZXQncyBjcmVhdGUgYSBtYXRyaXggdG8gd29yayB3aXRoCgpgYGB7ciBjb25kMDB9CnZlYzEgPC0gYygxLCAyLCAzLCA0LCA1LCA2KQoKdmVjMiA8LSBjKDcsIDgsIDksIDEwLCAxMSwgMTIpCgojIEFuZCBub3cgY29sdW1uLWJpbmQgKGNiaW5kKCkpIHRoZSB0d28gdmVjdG9ycy4KCmV4YW1wbGVfbWF0IDwtIGNiaW5kKHZlYzEsIHZlYzIpCgpleGFtcGxlX21hdApgYGAKCmBgYHtyIGNvbmQxfQpleGFtcGxlX21hdCA+IDkgIyBUaGlzIHJldHVybnMgVFJVRSBvciBGQUxTRSBmb3IgZWFjaCB2YWx1ZSBpbiB0aGUgb2JqZWN0LgpgYGAKCgpOb3cgaWYgd2UgcHV0IHRoaXMgY29uZGl0aW9uIGluIHNxdWFyZSBicmFja2V0cyB3ZSBnZXQgdGhlIHZhbHVlcyBmb3Igd2hpY2ggdGhlIGNvbmRpdGlvbiBpcyB0cnVlLgpgYGB7ciBjb25kMn0KZXhhbXBsZV9tYXRbZXhhbXBsZV9tYXQgPiA5XQpgYGAKCgojIyMgRXhlcmNpc2UgSUk6IFNlbGVjdGluZyBhbmQgcmVjb2RpbmcgZWxlbWVudHMKCkhlcmUgY29tZXMgdGhlIHNlY29uZCByb3VuZCBvZiBleGVyY2lzZXM6CgphKSBDcmVhdGUgdHdvIHZlY3RvcnMgYHZlYzFgIGFuZCBgdmVjMmAuCiAgICAtIGB2ZWMxYCBzaG91bGQgY29udGFpbiAxLCA1NiwgMjMsIDg5LCAtMyBhbmQgNSAoaW4gdGhhdCBvcmRlcikuCiAgICAtIGB2ZWMyYCBjb250YWlucyAyNCwgNzgsIDMyLCAyNywgOCBhbmQgMS4KICAgIApiKSBOb3cgc2VsZWN0IGVsZW1lbnRzIG9mIGB2ZWMxYCB0aGF0IGFyZSBncmVhdGVyIHRoYW4gNSBvciBzbWFsbGVyIHRoYW4gMC4KCmMpIE5leHQgc2V0IGB2ZWMxYCB0byB6ZXJvIGlmIGB2ZWMyYCBpcyBncmVhdGVyIHRoYW4gMzAgYW5kIHNtYWxsZXIgb3IgZXF1YWwgdG8gMzIuCgpQbGVhc2Ugc29sdmUgYWxsIHRocmVlIHN0ZXBzIGluIHRoZSBuZXh0IGNvZGUgY2h1bmsuCiAgICAKYGBge3IgRXhlcmNpc2VfSUksIGV2YWwgPSBULCBlcnJvcj1UUlVFfQojIGEpIENyZWF0ZSB0d28gdmVjdG9ycyBgdmVjMWAgYW5kIGB2ZWMyYAp2ZWMxIDwtIGMoMSwgNTYsIDIzLCA4OSwgLTMsIDUpCnZlYzIgPC0gYygyNCwgNzgsIDMyLCAyNywgOCwgMSkKCiMgYikgc2VsZWN0IGVsZW1lbnRzIG9mIGB2ZWMxYCB0aGF0IGFyZSBncmVhdGVyIHRoYW4gNSBvciBzbWFsbGVyIHRoYW4gMC4KdmVjMVt2ZWMxID4gNSB8IHZlYzEgPCAwXQoKIyBjKSBzZXQgYHZlYzFgIHRvIHplcm8gaWYgYHZlYzJgIGlzIGdyZWF0ZXIgdGhhbiAzMCBhbmQgc21hbGxlciBvciBlcXVhbCB0byAzMi4KdmVjMVt2ZWMyID4gMzAgJiB2ZWMyIDw9IDMyXSA8LSAwCnZlYzEKYGBgCgoKIyMgV29ya2luZyB3aXRoIGRhdGEuZnJhbWVzCgpXb3JraW5nIHdpdGggZGF0YSBmcmFtZXMgaXMgc2ltaWxhciB0byB3b3JraW5nIHdpdGggbWF0cmljZXMgYW5kIHZlY3RvcnMuCgojIyMgTG9hZGluZyBhbmQgbWFuaXB1bGF0aW5nIGRhdGEKClVzdWFsbHkgKGFuZCBlc3BlY2lhbGx5IGZvciB0aGlzIGNsYXNzKSB3ZSB3YW50IHRvIHdvcmsgd2l0aCBleGlzdGluZyBkYXRhc2V0cy4gUiBrbm93cyBhbmQgY2FuIGxvYWQgbW9zdCBvZiB0aGUgc3RhbmRhcmQgZm9ybWF0cyBvZiBkYXRhc2V0cywgbGlrZSBgLmNzdmAsIGAueGxzeGAgKEV4Y2VsKSwgYC5kdGFgIChTdGF0YSksIGAuc2F2YCAoU1BTUykgYW5kIG1hbnkgbW9yZS4gCgpTbyBmYXIgd2Ugb25seSB1c2VkIFIncyBiYXNlIGZ1bmN0aW9ucy4gSW4gb3JkZXIgdG8gdXNlIHNvbWUgbW9yZSBzb3BoaXN0aWNhdGVkIG9yIHNwZWNpYWwgUiBmdW5jdGlvbnMsIHdlIG5lZWQgdG8gbG9hZCBsaWJyYXJpZXMgb3IgcGFja2FnZXMgZmlyc3QuIFRoaW5rIG9mIHRoZXNlIGxpYnJhcmllcyBhcyBleHRyYSBhcHBzIHRoYXQgeW91IGNhbiBsb2FkIG9uIHlvdXIgc21hcnRwaG9uZXMgdG8gZXh0ZW5kIGl0cyBmdW5jdGlvbmFsaXR5LiAKClJpZ2h0IG5vdywgd2Ugd2FudCB0byBsb2FkIHRoZSBkYXRhc2V0LiBJbiBvcmRlciB0byB1c2UgdGhlIHN0YW5kYXJkIGJ1dCBmb3JlaWduIGRhdGFzZXRzIHdlIG5lZWQgdGhlICpmb3JlaWduKiBwYWNrYWdlLgoKRmlyc3QsIHdlIHdhbnQgdG8gaGF2ZSBhIGxvb2sgYXQgd2hhdCB0aGUgcGFja2FnZSBjYW4gZG8uCgpgYGB7cn0KcGFja2FnZURlc2NyaXB0aW9uKCJmb3JlaWduIikKCiMgT2sgdGhpcyBzZWVtcyB0byBiZSB1c2VmdWwuIFNvIGxldCdzIGxvYWQgdGhlIHBhY2thZ2UgdG8gdXNlIGl0LgpsaWJyYXJ5KGZvcmVpZ24pCmBgYAoKWW91IHdpbGwgb2Z0ZW4gY29tZSBhY3Jvc3MgZGF0YXNldHMgd2hpY2ggYXJlIHN0b3JlZCBhcyBTdGF0YSBkYXRhIGZpbGVzLiBUaG9zZSBmaWxlcyBoYXZlIHRoZSBleHRlbnNpb24gYC5kdGFgLgoKUmlnaHQgbm93LCB3ZSB3YW50IHRvIGxvYWQgdGhlIGRhdGEgc2V0IGNhbGxlZCBgd2VhdGhlcl9kYXRhX2dlcm1hbnlfMjAyMS5kdGFgIHdoaWNoIGlzIGFscmVhZHkgc3RvcmVkIHRoZSBgcmF3X2RhdGFgIGZvbGRlciBpbiBvdXIgZGlyZWN0b3J5OgoKYGBge3J9CndlYXRoZXJfZGF0YSA8LSByZWFkLmR0YSgicmF3X2RhdGEvd2VhdGhlcl9kYXRhX2dlcm1hbnlfMjAyMS5kdGEiKQpgYGAKCgpUaGUgZGF0YSBjb250YWlucyB5ZWFybHkgdGVtcGVyYXR1cmUgYXZlcmFnZXMgb2YgR2VybWFuIGNpdGllcyBhcyB3ZWxsIGFzIHRoZWlyIGdlb2dyYXBoaWNhbCBsb2NhdGlvbiAobG9uZ2l0dWRlIGFuZCBsYXRpdHVkZSkuIEl0IGNvbWVzIGZyb20gdGhlICJEZXV0c2NoZXIgV2V0dGVyZGllbnN0IiBhbmQgeW91IGNhbiBmaW5kIGl0IFtoZXJlXShodHRwczovL2NkYy5kd2QuZGUvcG9ydGFsLzIwMjIwNDAxMTAwNS9pbmRleC5odG1sKS4gTm93IHRoYXQgd2UgaGF2ZSBsb2FkZWQgdGhlIGRhdGEsIHdlIGNhbiBoYXZlIGEgbG9vayBhdCBpdC4KCldpdGggYGhlYWQoKWB3ZSBjYW4gbG9vayBhdCB0aGUgZmlyc3Qgc2l4IHJvd3Mgb2YgdGhlIGRhdGEgc2V0OgoKYGBge3IgZGYxfQpoZWFkKHdlYXRoZXJfZGF0YSkKYGBgCgpCdXQgd2UgY2FuIGFsc28gbG9vayBhdCB0aGUgZW50aXJlIGRhdGEgc2V0OgoKYGBge3IgZGYyLCByZXN1bHRzID0gImhpZGUifQp3ZWF0aGVyX2RhdGEKYGBgCgpJZiB3ZSBvbmx5IHdhbnQgdG8gbG9vayBhdCB0aGUgdmFyaWFibGUgbmFtZXMsIHdlIGNhbiB1c2UgYG5hbWVzKClgOgoKYGBge3IgZGYzfQpuYW1lcyh3ZWF0aGVyX2RhdGEpCmBgYAoKTm93IHdlIGNhbiB1c2Ugb3VyIHNlbGVjdGluZyBhYmlsaXRpZXMgb24gYSBkYXRhIGZyYW1lLiBBcyBiZWZvcmUgd2UgY2FuIHNlbGVjdCBlbGVtZW50cyB2aWEgdGhlaXIgbnVtZXJpYyBwb3NpdGlvbjoKCmBgYHtyIGRmNX0Kd2VhdGhlcl9kYXRhWzEsIDJdICMgZmlyc3Qgcm93LCBzZWNvbmQgY29sdW1uCmBgYAoKCmBgYHtyIGRmNn0Kd2VhdGhlcl9kYXRhWzE6MywgMV0gIyByb3dzIDEtMywgZmlyc3QgY29sdW1uCmBgYAoKQWRkaXRpb25hbGx5LCBhcyBjb2x1bW5zIHVzdWFsbHkgaGF2ZSBuYW1lcyBpbiBkYXRhIGZyYW1lcywgd2UgY2FuIHVzZSB0aGUgY29sdW1uIG5hbWVzIHRvIHNlbGVjdCB2YWx1ZXMgaW4gdHdvIHdheXMuCgpGaXJzdCwgd2UgY2FuIHB1dCB0aGUgY29sdW1uIG5hbWUgaW4gc3F1YXJlIGJyYWNrZXRzIGluc3RlYWQgb2YgYSBjb2x1bW4gbnVtYmVyOgoKYGBge3IgZGY3fQp3ZWF0aGVyX2RhdGFbMSwgImNpdHkiXQpgYGAKCmBgYHtyIGRmOCwgcmVzdWx0cyA9ICJoaWRlIn0Kd2VhdGhlcl9kYXRhWywgIm1lYW5fdGVtcCJdCmBgYAoKV2UgY2FuIGFsc28gbG9vayBhdCB0d28gdmFyaWFibGVzIGF0IG9uY2U6CgpgYGB7ciBkZjksIHJlc3VsdHMgPSAiaGlkZSJ9CndlYXRoZXJfZGF0YVssIGMoImNpdHkiLCAibWVhbl90ZW1wIildCmBgYAoKClNlY29uZCwgd2UgY2FuIGFsc28gc2VsZWN0IGFuIGVudGlyZSBjb2x1bW4gYnkgdXNpbmcgdGhlIGAkYCBvcGVyYXRvciB3aXRoIHRoZSBjb2x1bW4gbmFtZTogYGRhdGEuZnJhbWVfbmFtZSRjb2x1bW5fbmFtZWAuIEp1c3QgbGlrZSB0aGlzOgoKYGBge3IgZGYxMH0Kd2VhdGhlcl9kYXRhJG1lYW5fdGVtcApgYGAKCkNvbHVtbnMgZnJvbSBkYXRhIGZyYW1lcyBhcmUgZXNzZW50aWFsbHkgdmVjdG9ycy4gV2UgY2FuIHVzZSBhbGwgdGhlIG9wZXJhdGlvbnMgYW5kIGZ1bmN0aW9ucyB3ZSBjYW4gdXNlIGZvciB2ZWN0b3JzIChkZXBlbmRpbmcgb24gdGhlaXIgY2xhc3MuKQoKYGBge3IgZGYxMX0Kd2VhdGhlcl9kYXRhJG1lYW5fdGVtcFsxXSAjIEZvciBleGFtcGxlLCB3ZSBjYW4gc2VsZWN0IGFuIGVsZW1lbnQgb2YgdGhlIHZlY3RvcgpgYGAKCldoYXQgaWYgd2Ugd2FudCB0byBhZGQgYSBuZXcgdmFyaWFibGU/IExldCdzIGNyZWF0ZSBhIHZhcmlhYmxlIG5hbWVkICJjb2xkIi4KCmBgYHtyIGRmMTJ9CndlYXRoZXJfZGF0YSRjb2xkIDwtIDAKCiMgV2hhdCBkb2VzIHRoaXMgZG8/Cgp3ZWF0aGVyX2RhdGEkY29sZApgYGAKCk5vdywgd2Ugd2FudCB0byByZWNvZGUgImNvbGQiIHRvIDEgZm9yIGNpdGllcyB3aG9zZSBtZWFuIHRlbXBlcmF0dXJlIGlzIGxvd2VyIHRoYW4gOCBkZWdyZWVzIENlbHNpdXMuCgpgYGB7ciBkZjEzfQoKd2VhdGhlcl9kYXRhJGNvbGQgPC0gMAoKd2VhdGhlcl9kYXRhJGNvbGRbd2VhdGhlcl9kYXRhJG1lYW5fdGVtcCA8IDhdIDwtIDEKCiMgTGV0J3MgaGF2ZSBhIGxvb2sgYXQgYm90aCB2YXJpYWJsZXM6Cgp3ZWF0aGVyX2RhdGFbLCBjKCJjaXR5IiwgIm1lYW5fdGVtcCIsICJjb2xkIildCmBgYAoKCgoKIyMgQ2FsY3VsYXRpbmcgTWVhc3VyZXMgb2YgQ2VudHJhbCBUZW5kZW5jeSBhbmQgVmFyaWFiaWxpdHkKCkxldCdzIGxvb2sgYXQgdGhlIE1lYXN1cmVzIG9mIENlbnRyYWwgVGVuZGVuY3kgYW5kIFZhcmlhYmlsaXR5IGZyb20gdGhlIGxlY3R1cmUgKHN0YXJ0aW5nIGF0IHNsaWRlIDE3KS4KCkNvbnNpZGVyIHRoZSBmb2xsb3dpbmcgdmVjdG9yOgoKYGBge3J9CmV4YW1wbGVfdmVjIDwtIGMoMSwgMiwgMywgNCwgNSkKYGBgCgoKSG93IGNvdWxkIHdlIGNhbGN1bGF0ZSB0aGUgbWVhbiBvZiBgZXhhbXBsZV92ZWNgPwoKV2UgY291bGQgc2ltcGx5IGNhbGN1bGF0ZSBpdCAiYnkgaGFuZCI6CgpgYGB7cn0KKDEgKyAyICsgMyArIDQgKyA1KSAvIDUKYGBgCgpCdXQgdGhpcyBpcyBub3QgdmVyeSB1c2VmdWwgaWYgd2UgbG9vayBhdCBhbiBhY3R1YWwgdmVjdG9yIGluIG91ciBkYXRhIGZyYW1lLCBlLmcuLCBtZWFuIHRlbXBlcmF0dXJlOgoKYGBge3IgbWN0MX0Kd2VhdGhlcl9kYXRhJG1lYW5fdGVtcApgYGAKClR5cGluZyB1cCBhbGwgdGhlIGVudHJpZXMgaW5kaXZpZHVhbGx5IHdvdWxkIHRha2UgYSBsb3Qgb2YgdGltZS4gV2UgY291bGQgdXNlIHR3byBmdW5jdGlvbnMgdGhhdCB3ZSBhbHJlYWR5IGhhdmUgc2Vlbiwgc3VtIGFuZCBsZW5ndGguCgpgYGB7ciBtY3QyfQpzdW0od2VhdGhlcl9kYXRhJG1lYW5fdGVtcCkgLyBsZW5ndGgod2VhdGhlcl9kYXRhJG1lYW5fdGVtcCkKYGBgCgoKRm9ydHVuYXRlbHksIFIgcHJvdmlkZXMgYSBtdWNoIGVhc2llciB3YXkgdG8gY2FsY3VsYXRlIGEgbWVhbjoKCmBgYHtyIG1jdDN9Cm1lYW4od2VhdGhlcl9kYXRhJG1lYW5fdGVtcCkgIyBUaGF0IHdhcyBlYXN5LgpgYGAKCkJ1dCBiZSBzdXJlIHRoYXQgeW91ciB2ZWN0b3IgaXMgbnVtZXJpYy4gQ291bGQgeW91IGNhbGN1bGF0ZSB0aGUgbWVhbiBvZiBjaXR5PwoKYGBge3IgbWN0NH0Kd2VhdGhlcl9kYXRhJGNpdHkKYGBgCgpMZXQncyB0cnkgdG8gY2FsY3VsYXRlIHRoZSBtZWFuLgoKYGBge3IgbWN0NX0KbWVhbih3ZWF0aGVyX2RhdGEkY2l0eSkKYGBgCgpJdCBkb2VzIG5vdCB3b3JrISBBbmQgZXZlbiBieSBoYW5kIHdlIGNvdWxkIG5vdCBjYWxjdWxhdGUgdGhlIG1lYW4gb2YgY2hhcmFjdGVyIHZhbHVlZCB2ZWN0b3JzLiAKCkhlcmUgaXMgYW4gb3ZlcnZpZXcgb3ZlciBmdW5jdGlvbnMgZm9yIG1lYXN1cmVzIG9mIGNlbnRyYWxpdHkgYW5kIHZhcmlhYmlsaXR5OgoKICAtIE1lYW46IGBtZWFuKClgCiAgLSBNZWRpYW46IGBtZWRpYW4oKWAKICAtIFZhcmlhbmNlOiBgdmFyKClgCiAgLSBTdGFuZGFyZCBEZXZpYXRpb246IGBzZCgpYAogIC0gUmFuZ2U6IGByYW5nZSgpYAogIC0gSW50ZXItcXVhcnRpbGUgcmFuZ2U6IGBJUVIoKWAKICAKWW91IGNhbiB0cnkgdGhlbSBvdXQgaGVyZToKCmBgYHtyIG1jdDZ9CiMgTWVkaWFuCgptZWRpYW4od2VhdGhlcl9kYXRhJG1lYW5fdGVtcCkKCiMgVmFyaWFuY2UKCnZhcih3ZWF0aGVyX2RhdGEkbWVhbl90ZW1wKQoKIyBTdGFuZGFyZCBkZXZpYXRpb24KCnNkKHdlYXRoZXJfZGF0YSRtZWFuX3RlbXApCgojIFJhbmdlCgpyYW5nZSh3ZWF0aGVyX2RhdGEkbWVhbl90ZW1wKQoKIyBJbnRlciBRdWFydGlsZSBSYW5nZSAoSVFSKQoKSVFSKHdlYXRoZXJfZGF0YSRtZWFuX3RlbXApCmBgYAoKVW5mb3J0dW5hdGVseSwgdGhlcmUgaXMgbm8gZGlyZWN0IGZ1bmN0aW9uIHRvIGdldCB0aGUgbW9kZS4KVGhlIHNvbHV0aW9ucyB5b3Ugd2lsbCBmaW5kIG9ubGluZSBhcmUgYWxsIGEgYml0IGFkdmFuY2VkLiAKU28gdGhlIGVhc2llc3Qgc29sdXRpb24gaXMgdG8gbG9vayBmb3IgdGhlIG1vZGUgdXNpbmcgYSBmcmVxdWVuY3kgdGFibGUuCgpgYGB7ciBtY3Q3fQp0YWJsZSh3ZWF0aGVyX2RhdGEkY29sZCkKYGBgCgpUaGUgYHRhYmxlKClgIGZ1bmN0aW9uIHNob3dzIHlvdSBob3cgb2Z0ZW4gZWFjaCB2YWx1ZSBpcyBpbiB0aGUgdmVjdG9yLiBZb3UgY2FuIG5vdyBpZGVudGlmeSB0aGUgbW9zdCBmcmVxdWVudCB2YWx1ZS4gCgoKIyMjICBFeGVyY2lzZSBJSUk6IE1hbmlwdWxhdGluZyBkYXRhCgpOb3cgd2Ugd2lsbCB3b3JrIHdpdGggdGhlIGB3ZWF0aGVyX2RhdGFgIGRhdGEgc2V0LiBJdCBpcyBhbHJlYWR5IGxvYWRlZCBmb3IgeW91IGFuZCB5b3UgY2FuIHVzZSBpdCByaWdodCBhd2F5LgoKYSkgU2hvdyB0aGUgdmFyaWFibGUgYG1lYW5fdGVtcGAgaWYgaXQgaXMgb3ZlciAxMC4KCmIpIEdlbmVyYXRlIGEgbmV3IHZhcmlhYmxlIGFuZCBjYWxsIGl0IGBob3RgIHRoYXQgaXMgemVybyBmb3IgKm1lYW4gdGVtcGVyYXR1cmUqIDwgMTAgYW5kIDEgZm9yICptZWFuIHRlbXBlcmF0dXJlKiA+IDEwIGRlZ3JlZSBDZWxzaXVzLgoKYykgSGF2ZSBhIGxvb2sgYXQgeW91ciBkYXRhIHNldC4KClBsZWFzZSBzb2x2ZSBhbGwgdGhyZWUgc3RlcHMgaW4gdGhlIG5leHQgY29kZSBjaHVuay4KCmBgYHtyIEV4ZXJjaXNlX0lJSSwgZXZhbCA9IFQsIGVycm9yPVRSVUV9CiMgYSkgU2hvdyB0aGUgdmFyaWFibGUgYG1lYW5fdGVtcGAgaWYgaXQgaXMgb3ZlciAxMC4Kd2VhdGhlcl9kYXRhJG1lYW5fdGVtcFt3ZWF0aGVyX2RhdGEkbWVhbl90ZW1wID4gMTBdCgojIGIpIEdlbmVyYXRlIGEgbmV3IHZhcmlhYmxlIGFuZCBjYWxsIGl0IGBob3RgIHRoYXQgaXMgemVybyBmb3IgCiMgKm1lYW4gdGVtcGVyYXR1cmUqIDwgMTAgYW5kIDEgZm9yICptZWFuIHRlbXBlcmF0dXJlKiA+IDEwIGRlZ3JlZSBDZWxzaXVzLgp3ZWF0aGVyX2RhdGEkaG90IDwtIDAKd2VhdGhlcl9kYXRhJGhvdFt3ZWF0aGVyX2RhdGEkbWVhbl90ZW1wID4gMTBdIDwtIDEKCiMgYykgSGF2ZSBhIGxvb2sgYXQgeW91ciBkYXRhIHNldC4Kd2VhdGhlcl9kYXRhCmBgYAoKIyMjIEV4ZXJjaXNlIElWOiBTdWJzZXR0aW5nCgpUaGlzIGlzIGEgbGl0dGxlIHRyaWNraWVyOiBDYW4geW91IGZpbmQgdGhlIGhvdHRlc3QgYW5kIGNvbGRlc3QgY2l0eSBpbiBHZXJtYW55IDIwMjE/IAoKSGludDogVGhlIGZ1bmN0aW9ucyBgbWluKClgIGFuZCBgbWF4KClgIGhlbHAgeW91IHRvIGZpbmQgdGhlIG1pbmltdW0gYW5kIG1heGltdW0gdmFsdWVzIG9mIGEgdmVjdG9yIG9yIHZhcmlhYmxlLiBDb21iaW5lIHRoYXQgd2l0aCB5b3VyIG5ld2x5IGxlYXJuZWQgc3Vic2V0dGluZyBza2lsbHMgYW5kIHlvdSdsbCBmaW5kIHRoZSBhbnN3ZXIuCgpgYGB7ciBFeGVyY2lzZV9JVl8xLCBldmFsID0gVCwgZXJyb3I9VFJVRX0KIyBob3R0ZXN0IGNpdHkKd2VhdGhlcl9kYXRhW3dlYXRoZXJfZGF0YSRtZWFuX3RlbXAgPT0gbWF4KHdlYXRoZXJfZGF0YSRtZWFuX3RlbXApLF0KCiMgY29sZGVzdCBjaXR5CndlYXRoZXJfZGF0YVt3ZWF0aGVyX2RhdGEkbWVhbl90ZW1wID09IG1pbih3ZWF0aGVyX2RhdGEkbWVhbl90ZW1wKSxdCmBgYAoKIyMjIEV4ZXJjaXNlIFY6IE1lYXN1cmVzIG9mIGNlbnRyYWwgdGVuZGVuY3kKCldlIHdpbGwgY29udGludWUgd29ya2luZyB3aXRoIHRoZSB3ZWF0aGVyIGRhdGEgc2V0CgphKSBDYWxjdWxhdGUgdGhlIG1lYW4gdmFsdWUgb2YgbGF0aXR1ZGUgYW5kIHNhdmUgdGhlIHJlc3VsdCBhcyBgbWVhbl9sYXRpdHVkZWAuCiAgICAgIApgYGB7ciBFeGVyY2lzZV9WXzEsIGV2YWwgPSBULCBlcnJvcj1UUlVFfQptZWFuX2xhdGl0dWRlIDwtIG1lYW4od2VhdGhlcl9kYXRhJGxhdGl0dWRlKQptZWFuX2xhdGl0dWRlCmBgYAoKYikgQ2FsY3VsYXRlIHRoZSB2YXJpYW5jZSBvZiBsYXRpdHVkZSBhbmQgc2F2ZSB0aGUgcmVzdWx0IGFzIGB2YXJfbGF0aXR1ZGVgLgoKYGBge3IgRXhlcmNpc2VfVl8yLCBldmFsID0gVCwgZXJyb3I9VFJVRX0KdmFyX2xhdGl0dWRlIDwtIHZhcih3ZWF0aGVyX2RhdGEkbGF0aXR1ZGUpCnZhcl9sYXRpdHVkZQpgYGAKCmMpIENhbGN1bGF0ZSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIGxhdGl0dWRlIGFuZCBzYXZlIHRoZSByZXN1bHQgYXMgYHNkX2xhdGl0dWRlYC4KCmBgYHtyIEV4ZXJjaXNlX1ZfMywgZXZhbCA9IFQsIGVycm9yPVRSVUV9CnNkX2xhdGl0dWRlIDwtIHNkKHdlYXRoZXJfZGF0YSRsYXRpdHVkZSkKc2RfbGF0aXR1ZGUKYGBgCgojIyBQbG90dGluZyBkYXRhCgpMZXQncyBoYXZlIGEgc2hvcnQgbG9vayBhdCBvdXIgZGF0YSBhZ2Fpbi4KUmVtZW1iZXI6IGBoZWFkKClgIHNob3dzIHlvdSB0aGUgZmlyc3Qgc2l4IGVudHJpZXMgb2YgeW91ciBkYXRhLiBJdCBpcyB2ZXJ5IHVzZWZ1bCB0byBnZXQgYSBsb29rIGF0IHRoZSBkYXRhIHN0cnVjdHVyZSB3aGVuIHlvdSBoYXZlIGEgbG90IG9mIHJvd3MgaW4geW91ciBkYXRhc2V0LgoKYGBge3J9CmhlYWQod2VhdGhlcl9kYXRhKQpgYGAKCgojIyMgUGxvdHMgZm9yIGJpdmFyaWF0ZSBkaXN0cmlidXRpb25zCgojIyMjIFNjYXR0ZXJwbG90cwoKTm93IHdlIGNhbiBjcmVhdGUgYSBzaW1wbGUgc2NhdHRlcnBsb3Q6CgpgYGB7ciB2aXMxfQpwbG90KAogIHggPSB3ZWF0aGVyX2RhdGEkbG9uZ2l0dWRlLAogIHkgPSB3ZWF0aGVyX2RhdGEkbWVhbl90ZW1wCikKYGBgCgpUbyBnZXQgYSBuaWNlciBwbG90LCB3ZSBjYW4gYWRqdXN0IG1hbnkgdGhpbmdzLiBXZSBzdWdnZXN0IHRvIGFsd2F5cyBleHBsaWNpdGx5IG1ha2UgdGhvc2UgYWRqdXN0bWVudHMgaW4gdGhlIHNhbWUgb3JkZXIuCgpgYGB7ciB2aXMyfQpwbG90KAogIHggPSB3ZWF0aGVyX2RhdGEkbG9uZ2l0dWRlLAogIHkgPSB3ZWF0aGVyX2RhdGEkbWVhbl90ZW1wLAogIHR5cGUgPSAicCIsICMgVGhpcyBleHBsaWNpdGx5IHNheXMgdGhhdCB3ZSB3YW50IHBvaW50cy4gWW91IGNvdWxkIGFsc28gdHJ5ICJsIi4KICBtYWluID0gIk1lYW4gdGVtcGVyYXR1cmVzIG9mIEdlcm1hbiBjaXRpZXMiLCAjIFRoaXMgYWRkcyBhIHRpdGxlIHRvIHRoZSBwbG90CiAgeGxhYiA9ICJMb25naXR1ZGUgKFdlc3QgLSBFYXN0KSIsICMgVGhpcyBsYWJlbHMgdGhlIHgtYXhpcy4KICB5bGFiID0gIk1lYW4gVGVtcGVyYXR1cmUgaW4gMjAyMSIsICMgV2hhdCBkb2VzIHRoaXMgZG8gdGhlbj8KICBsYXMgPSAxLCAjIFRoaXMgYWZmZWN0cyB0aGUgdGljayBsYWJlbHMgb2YgdGhlIHktYXhpcy4KICBwY2ggPSAxOSwgIyBIZXJlIHdlIGNob29zZSB3aGF0IHN5bWJvbHMgd2Ugd2FudCB0byBwbG90LgogIGNvbCA9ICJibGFjayIsICMgV2hhdCBjb2xvciBzaG91bGQgdGhlIHN5bWJvbHMgaGF2ZT8KICBmcmFtZSA9IEYgIyBObyBib3ggYXJvdW5kIHRoZSBwbG90LgopCmBgYAoKIyMjIEFkZGluZyBDb2xvciB0byBQbG90cyB3aXRoIFZpcmlkaXMKCldlIGNhbiBhbHNvIGFkanVzdCB0aGUgY29sb3JzLiBMZXQncyBoaWdobGlnaHQgTWFubmhlaW0hCgo+IDxpIGNsYXNzPSJmYSBmYS1ncmFkdWF0aW9uLWNhcCI+PC9pPiBQcm8gVGlwOiBUbyBjb2xvciB1cCB5b3VyIGRhdGEgdmlzdWFsaXphdGlvbnMsIHVzZSB0aGUgPGEgaHJlZj0iaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3ZpcmlkaXMvdmlnbmV0dGVzL2ludHJvLXRvLXZpcmlkaXMuaHRtbCIgc3R5bGU9ImNvbG9yOndoaXRlIj52aXJpZGlzLXBhY2thZ2U8L2E+LiAKClZpcmlkaXMgY29sb3JzIG1ha2UgaXQgZWFzaWVyIHRvIHJlYWQgYnkgdGhvc2Ugd2l0aCBjb2xvcmJsaW5kbmVzcyBhbmQgcHJpbnQgd2VsbCBpbiBncmV5c2NhbGUuIFlvdSBwcm9iYWJseSBkb24ndCB3YW50IHRvIGhhdmUgcGxvdHMgbGlrZSB0aGlzOgoKIVtdKGh0dHBzOi8vZmxvd2luZ2RhdGEuY29tL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDEyLzExL0RpdmlkZWQtbmF0aW9uLmpwZykKCldlIGZpcnN0IG5lZWQgYSB2ZWN0b3IgdGhhdCBnaXZlcyB1cyB0aGUgcmlnaHQgY29sb3JzIHdpdGggcmVzcGVjdCB0byB0aGUgY2l0eSB2YXJpYWJsZS4KCmBgYHtyfQpsaWJyYXJ5KHZpcmlkaXMpCgojIHdlIG5lZWQgdHdvIGNvbG9ycywgdGhpcyBpcyBob3cgd2UgZ2V0IHRoZW06CnR3b19jb2xvcnMgPC0gdmlyaWRpcygyKQoKdHdvX2NvbG9ycyAjIHRoZXNlIGFyZSBzby1jYWxsZWQgSEVYIGNvbG9yIGNvZGVzCgojIHdlIHVzZSB0aGUgZmlyc3QgY29sb3IgZm9yIG1hbGVzIGFuZCB0aGUgc2Vjb25kIGZvciBmZW1hbGVzCm1hbm5oZWltX2NvbG9yIDwtIGlmZWxzZSh3ZWF0aGVyX2RhdGEkY2l0eSA9PSAiTWFubmhlaW0iLCB0d29fY29sb3JzWzFdLCB0d29fY29sb3JzWzJdKQoKIyBsZXQncyBoYXZlIGEgbG9vazoKdGFibGUobWFubmhlaW1fY29sb3IpIApgYGAKCk5vdyB3ZSBjYW4gdXNlIHRoaXMgdmVjdG9yIHRvIHNwZWNpZnkgdGhlIGNvbG9yIHJlc3BlY3RpdmUgdG8gTWFubmhlaW06CgpgYGB7ciB2aXMzfQpwbG90KAogIHggPSB3ZWF0aGVyX2RhdGEkbG9uZ2l0dWRlLAogIHkgPSB3ZWF0aGVyX2RhdGEkbWVhbl90ZW1wLAogIHR5cGUgPSAicCIsICMgVGhpcyBleHBsaWNpdGx5IHNheXMgdGhhdCB3ZSB3YW50IHBvaW50cy4gWW91IGNvdWxkIGFsc28gdHJ5ICJsIi4KICBtYWluID0gIk1lYW4gdGVtcGVyYXR1cmVzIG9mIEdlcm1hbiBjaXRpZXMiLCAjIFRoaXMgYWRkcyBhIHRpdGxlIHRvIHRoZSBwbG90CiAgeGxhYiA9ICJMb25naXR1ZGUgKFdlc3QgLSBFYXN0KSIsICMgVGhpcyBsYWJlbHMgdGhlIHgtYXhpcy4KICB5bGFiID0gIk1lYW4gVGVtcGVyYXR1cmUgaW4gMjAyMSIsICMgV2hhdCBkb2VzIHRoaXMgZG8gdGhlbj8KICBsYXMgPSAxLCAjIFRoaXMgYWZmZWN0cyB0aGUgdGljayBsYWJlbHMgb2YgdGhlIHktYXhpcy4KICBwY2ggPSAxOSwgIyBIZXJlIHdlIGNob29zZSB3aGF0IHN5bWJvbHMgd2Ugd2FudCB0byBwbG90LgogIGNvbCA9IG1hbm5oZWltX2NvbG9yLCAjIEluc3RlYWQgb2YganVzdCBibGFjayB3ZSBub3cgdXNlIHRoZSBjb2xvciB2ZWN0b3IuCiAgZnJhbWUgPSBGICMgTm8gZnJhbWUgYXJvdW5kIHRoZSBwbG90LgopCmBgYAoKTm93IHRoYXQgd2UgdXNlIGRpZmZlcmVudCBjb2xvcnMsIHdlIGFsc28gbmVlZCBhIGxlZ2VuZCB0byBrbm93IHdoaWNoIGNvbG9yIGlzIHdoaWNoLgoKYGBge3IgdmlzNH0KcGxvdCgKICB4ID0gd2VhdGhlcl9kYXRhJGxvbmdpdHVkZSwKICB5ID0gd2VhdGhlcl9kYXRhJG1lYW5fdGVtcCwKICB0eXBlID0gInAiLCAjIFRoaXMgZXhwbGljaXRseSBzYXlzIHRoYXQgd2Ugd2FudCBwb2ludHMuIFlvdSBjb3VsZCBhbHNvIHRyeSAibCIuCiAgbWFpbiA9ICJNZWFuIHRlbXBlcmF0dXJlcyBvZiBHZXJtYW4gY2l0aWVzIiwgIyBUaGlzIGFkZHMgYSB0aXRsZSB0byB0aGUgcGxvdAogIHhsYWIgPSAiTG9uZ2l0dWRlIChXZXN0IC0gRWFzdCkiLCAjIFRoaXMgbGFiZWxzIHRoZSB4LWF4aXMuCiAgeWxhYiA9ICJNZWFuIFRlbXBlcmF0dXJlIGluIDIwMjEiLCAjIFdoYXQgZG9lcyB0aGlzIGRvIHRoZW4/CiAgbGFzID0gMSwgIyBUaGlzIGFmZmVjdHMgdGhlIHRpY2sgbGFiZWxzIG9mIHRoZSB5LWF4aXMuCiAgcGNoID0gMTksICMgSGVyZSB3ZSBjaG9vc2Ugd2hhdCBzeW1ib2xzIHdlIHdhbnQgdG8gcGxvdC4KICBjb2wgPSBtYW5uaGVpbV9jb2xvciwgIyBJbnN0ZWFkIG9mIGp1c3QgYmxhY2sgd2Ugbm93IHVzZSB0aGUgY29sb3IgdmVjdG9yLgogIGZyYW1lID0gRiAjIE5vIGZyYW1lIGFyb3VuZCB0aGUgcGxvdC4KKQpsZWdlbmQoCiAgImJvdHRvbWxlZnQiLCAjIExvY2F0ZSB0aGUgbGVnZW5kIGluIHRoZSB0b3BsZWZ0IGNvcm5lci4KICBsZWdlbmQgPSBjKCJNYW5uaGVpbSIsICJvdGhlciIpLCAjIEdpdmUgaXQgbGFiZWxzLgogIHBjaCA9IDE5LCAjIFNwZWNpZnkgc3ltYm9scyBhcyBpbiB0aGUgc2NhdHRlcnBsb3QuCiAgY29sID0gdHdvX2NvbG9ycywgIyBTcGVjaWZ5IGNvbG9ycy4KICBidHkgPSAibiIgIyBObyBib3ggYXJvdW5kIHRoZSBsZWdlbmQuCikKYGBgCgpgYGB7cn0KcGxvdCgKICB4ID0gd2VhdGhlcl9kYXRhJGxvbmdpdHVkZSwKICB5ID0gd2VhdGhlcl9kYXRhJG1lYW5fdGVtcCwKICB0eXBlID0gInAiLCAjIFRoaXMgZXhwbGljaXRseSBzYXlzIHRoYXQgd2Ugd2FudCBwb2ludHMuIFlvdSBjb3VsZCBhbHNvIHRyeSAibCIuCiAgbWFpbiA9ICJNZWFuIHRlbXBlcmF0dXJlcyBvZiBHZXJtYW4gY2l0aWVzIiwgIyBUaGlzIGFkZHMgYSB0aXRsZSB0byB0aGUgcGxvdAogIHhsYWIgPSAiTG9uZ2l0dWRlIChXZXN0IC0gRWFzdCkiLCAjIFRoaXMgbGFiZWxzIHRoZSB4LWF4aXMuCiAgeWxhYiA9ICJNZWFuIFRlbXBlcmF0dXJlIGluIDIwMjEiLCAjIFdoYXQgZG9lcyB0aGlzIGRvIHRoZW4/CiAgbGFzID0gMSwgIyBUaGlzIGFmZmVjdHMgdGhlIHRpY2sgbGFiZWxzIG9mIHRoZSB5LWF4aXMuCiAgcGNoID0gMTksICMgSGVyZSB3ZSBjaG9vc2Ugd2hhdCBzeW1ib2xzIHdlIHdhbnQgdG8gcGxvdC4KICBjb2wgPSBtYW5uaGVpbV9jb2xvciwgIyBJbnN0ZWFkIG9mIGp1c3QgYmxhY2sgd2Ugbm93IHVzZSB0aGUgY29sb3IgdmVjdG9yLgogIGZyYW1lID0gRiAjIE5vIGZyYW1lIGFyb3VuZCB0aGUgcGxvdC4KKQojIHdlIHdhbnQgdG8gbGFiZWwgdGhlIHBvaW50IHRoYXQgcmVmZXJzIHRvIE1hbm5oZWltCiMgV2UgY2FuIGRvIHRoYXQgd2l0aCB0aGUgdGV4dCgpIGZ1bmN0aW9uLAojIEJ1dCB3ZSBuZWVkIHRvIHN1YnNldCB0aGUgZGF0YSwgc28gdGhhdCBvbmx5IE1hbm5oZWltIGdldHMgbGFiZWxsZWQsCiMgYW5kIG5vIG90aGVyIGNpdHkKdGV4dCgKICB4ID0gd2VhdGhlcl9kYXRhJGxvbmdpdHVkZVt3ZWF0aGVyX2RhdGEkY2l0eSA9PSAiTWFubmhlaW0iXSwgIyBzdWJzZXQgTWFubmhlaW0KICB5ID0gd2VhdGhlcl9kYXRhJG1lYW5fdGVtcFt3ZWF0aGVyX2RhdGEkY2l0eSA9PSAiTWFubmhlaW0iXSwgIyBzdWJzZXQgTWFubmhlaW0KICBsYWJlbHMgPSAiTWFubmhlaW0iLCAjIGxhYmVsIE1hbm5oZWltIGFzICJNYW5uaGVpbSIKICBwb3MgPSA0ICMgcG9zaXRpb24gdGhlIGxhYmVsIHJpZ2h0IHRvIHRoZSBwb2ludAopCmBgYAoKCiMjIyBQbG90cyBmb3IgdW5pdmFyaWF0ZSBkaXN0cmlidXRpb25zCgojIyMjIEhpc3RvZ3JhbXMKCk5vdyB3ZSB3YW50IHRvIHZpc3VhbGl6ZSBtZWFuIHRlbXBlcmF0dXJlIHdpdGggYSBoaXN0b2dyYW0uIFRoaXMgaXMgaG93IHlvdSBnZXQgYSBzdGFuZGFyZCBoaXN0b2dyYW06CgpgYGB7ciB2aXM1fQpoaXN0KHggPSB3ZWF0aGVyX2RhdGEkbWVhbl90ZW1wKSAjIFRoYXQncyBpbnR1aXRpdmUsIGJ1dCBkb2VzIG5vdCBsb29rIHRvbyBncmVhdApgYGAKCkFnYWluLCB3ZSBjYW4gYWRqdXN0IG1hbnkgdGhpbmdzIHRvIG1ha2UgaXQgbmljZXIuCgpgYGB7ciB2aXM2fQpoaXN0KAogIHggPSB3ZWF0aGVyX2RhdGEkbWVhbl90ZW1wLCAjIEZvciBhIGhpc3RvZ3JhbSB3ZSBvbmx5IHNwZWNpZnkgeC4KICBicmVha3MgPSA1MCwgIyBzcGVjaWZ5IHRoZSBudW1iZXIgb2YgYmlucwogIG1haW4gPSAiQSBIaXN0b2dyYW0iLAogIHhsYWIgPSAiTWVhbiB0ZW1wZXJhdHVyZSBpbiBkZWdyZWUgQ2Vsc2l1cyIsCiAgeWxhYiA9ICJOdW1iZXIgb2Ygb2JzZXJ2YXRpb25zIiwKICBsYXMgPSAxLCAjIHNoaWZ0IHRoZSB5LWF4aXMgbGFiZWxzIAogIGNvbCA9IHZpcmlkaXMoMSksICMgT25lIGNvbG9yIG9ubHkgKGZpcnN0IGNvbG9yIGZyb20gdmlyaWRpcykKICBib3JkZXIgPSAid2hpdGUiICMgVGhhdCdzIHRoZSBjb2xvciBvZiB0aGUgYmluIGJvcmRlcnMuCikKYGBgCgojIyMjIERlbnNpdHkgUGxvdHMKCldlIGNhbiBhbHNvIGNyZWF0ZSBkZW5zaXR5IHBsb3RzLgoKYGBge3IgdmlzN30KcGxvdCgKICBkZW5zaXR5KHdlYXRoZXJfZGF0YSRtZWFuX3RlbXApLCAjIGRlbnNpdHkoKSB0YWtlcyBjYXJlIG9mIHgsIHkgYW5kIHR5cGUuCiAgbWFpbiA9ICJBIFNpbXBsZSBEZW5zaXR5IFBsb3QiLAogIHhsYWIgPSAiTWVhbiB0ZW1wZXJhdHVyZSBpbiBkZWdyZWUgQ2Vsc2l1cyIsCiAgeWxhYiA9ICIiLCAjIFRoZSB5LWF4aXMgaXMgbm90IHJlYWxseSBtZWFuaW5nZnVsIGhlcmUuCiAgY29sID0gdmlyaWRpcygxKSwKICBsd2QgPSAyLCAjIENvbnRyb2wgdGhlIHdpZHRoIG9mIHRoZSBsaW5lCiAgZnJhbWUgPSBGLAogIHlheHQgPSAibiIgIyBSZW1vdmUgdGhlIHktYXhpcy4KKQpgYGAKCkFuZCB3ZSBjYW4gYWxzbyBmaWxsIHRoZSBhcmUgdW5kZXJuZWF0aCB0aGUgY3VydmU6CgpgYGB7ciB2aXM4fQpwbG90KAogIGRlbnNpdHkod2VhdGhlcl9kYXRhJG1lYW5fdGVtcCksICMgZGVuc2l0eSgpIHRha2VzIGNhcmUgb2YgeCwgeSBhbmQgdHlwZS4KICBtYWluID0gIkEgU2ltcGxlIERlbnNpdHkgUGxvdCIsCiAgeGxhYiA9ICJNZWFuIHRlbXBlcmF0dXJlIGluIGRlZ3JlZSBDZWxzaXVzIiwKICB5bGFiID0gIiIsICMgVGhlIHktYXhpcyBpcyBub3QgcmVhbGx5IG1lYW5pbmdmdWwgaGVyZS4KICBjb2wgPSB2aXJpZGlzKDEpLAogIGx3ZCA9IDIsICMgQ29udHJvbCB0aGUgd2lkdGggb2YgdGhlIGxpbmUKICBmcmFtZSA9IEYsCiAgeWF4dCA9ICJuIiAjIFJlbW92ZSB0aGUgeS1heGlzLgopCgpwb2x5Z29uKGRlbnNpdHkod2VhdGhlcl9kYXRhJG1lYW5fdGVtcCksIAogICAgICAgIGNvbCA9IHZpcmlkaXMoMSwgYWxwaGEgPSAwLjUpICMgc2FtZSBjb2xvciBidXQgNTAlIHRyYW5zcGFyZW50CiAgICAgICAgKQpgYGAKCiMjIyMgLi4uYW5kIEJveHBsb3RzCgpgYGB7ciB2aXM5fQpib3hwbG90KAogIHggPSB3ZWF0aGVyX2RhdGEkbWVhbl90ZW1wLCAjIEFzIGZvciBoaXN0b2dyYW1zIHdlIG9ubHkgc3BlY2lmeSB4LgogIG1haW4gPSAiQm94cGxvdCBvZiBNZWFuIHRlbXBlcmF0dXJlIGluIGRlZ3JlZSBDZWxzaXVzIiwKICB5bGFiID0gIk1lYW4gdGVtcGVyYXR1cmUgaW4gZGVncmVlIENlbHNpdXMiLAogIGxhcyA9IDEsCiAgY29sID0gcGxhc21hKDEpLAogIGZyYW1lID0gRgopCmBgYAoKT3IgYSBob3Jpem9udGFsIGJveHBsb3QuCgpgYGB7ciB2aXMxMH0KYm94cGxvdCgKICB4ID0gd2VhdGhlcl9kYXRhJG1lYW5fdGVtcCwKICBob3Jpem9udGFsID0gVCwgIyBXaXRoIGhvcml6b250YWwgPSBUIHdlIHJvdGF0ZSB0aGUgYm94cGxvdC4KICBtYWluID0gIkhvcml6b250YWwgQm94cGxvdCBvZiBNZWFuIHRlbXBlcmF0dXJlIGluIGRlZ3JlZSBDZWxzaXVzIiwKICB4bGFiID0gIk1lYW4gdGVtcGVyYXR1cmUgaW4gZGVncmVlIENlbHNpdXMiLAogIGxhcyA9IDEsCiAgZnJhbWUgPSBGCikKYGBgCgpZb3UgbGVhcm5lZCBpbiB0aGUgbGVjdHVyZSB0aGF0IGJveHBsb3RzIGhhdmUgc29tZSBkaXNhZHZhbnRhZ2VzLgoKPiA8aSBjbGFzcz0iZmEgZmEtaGFuZC1vLXJpZ2h0Ij48L2k+IFZpb2xpbiBwbG90cyBhcmUgYSB2ZXJ5IG5pY2UgYWx0ZXJuYXRpdmUhCgpUaGlzIGlzIGhvdyB5b3UgZ2V0IHRoZW06CgpgYGB7ciB2aXMxMX0KbGlicmFyeSh2aW9wbG90KQoKdmlvcGxvdCgKICB4ID0gd2VhdGhlcl9kYXRhJG1lYW5fdGVtcCwKICBob3Jpem9udGFsID0gVCwgIyBXaXRoIGhvcml6b250YWwgPSBUIHdlIHJvdGF0ZSB0aGUgYm94cGxvdC4KICBtYWluID0gIkhvcml6b250YWwgVmlvbGlucGxvdCBvZiBNZWFuIHRlbXBlcmF0dXJlIGluIGRlZ3JlZSBDZWxzaXVzIiwKICB4YXh0ID0gIm4iLAogIHhsYWIgPSAiTWVhbiB0ZW1wZXJhdHVyZSBpbiBkZWdyZWUgQ2Vsc2l1cyIsCiAgYnR5ID0gIm4iLAogIGF4ZXMgPSBGQUxTRSwKICBuYW1lcyA9ICIiLAogIGJvcmRlciA9IE5BCikKYGBgCgoKIyMjICBFeGVyY2lzZSBWSTogUGxvdHRpbmcKCk9rYXksIGxhc3Qgcm91bmQgb2YgZXhlcmNpc2VzIGZvciB0b2RheToKIAphKSBNYWtlIGEgaGlzdG9ncmFtIG9mIHRoZSAqbGF0aXR1ZGUqIHZhcmlhYmxlLiAKCmBgYHtyIEV4ZXJjaXNlX1ZJXzEsIGV2YWwgPSBULCBlcnJvcj1UUlVFfQpoaXN0KAogIHggPSB3ZWF0aGVyX2RhdGEkbGF0aXR1ZGUsICMgRm9yIGEgaGlzdG9ncmFtIHdlIG9ubHkgc3BlY2lmeSB4LgopCmBgYAogICAKYikgTWFrZSB0aGUgcGxvdCBuaWNlIGxvb2tpbmcgKE5hbWUgdGhlIGF4ZXMsIG1haW4gdGl0bGUsIGNvbG9ycy4uLikKCmBgYHtyIEV4ZXJjaXNlX1ZJXzIsIGV2YWwgPSBULCBlcnJvcj1UUlVFfQpoaXN0KAogIHggPSB3ZWF0aGVyX2RhdGEkbGF0aXR1ZGUsICMgRm9yIGEgaGlzdG9ncmFtIHdlIG9ubHkgc3BlY2lmeSB4LgogIGJyZWFrcyA9IDUwLCAjIHNwZWNpZnkgdGhlIG51bWJlciBvZiBiaW5zCiAgbWFpbiA9ICJBIEhpc3RvZ3JhbSIsCiAgeGxhYiA9ICJMYXRpdHVkZSIsCiAgeWxhYiA9ICJOdW1iZXIgb2Ygb2JzZXJ2YXRpb25zIiwKICBsYXMgPSAxLCAjIHNoaWZ0IHRoZSB5LWF4aXMgbGFiZWxzIAogIGNvbCA9IHZpcmlkaXMoMSksICMgT25lIGNvbG9yIG9ubHkgKGZpcnN0IGNvbG9yIGZyb20gdmlyaWRpcykKICBib3JkZXIgPSAid2hpdGUiICMgVGhhdCdzIHRoZSBjb2xvciBvZiB0aGUgYmluIGJvcmRlcnMuCikKYGBgCgoKCgojIyBSZWNhcAoKV2hhdCB3ZSBsZWFybmVkIGluIHRoaXMgc2Vzc2lvbjoKICAKICAxLiBIb3cgdG8gd29yayB3aXRoIFIgYW5kIEdpdEh1Yi4KICAyLiBBc3NpZ25pbmcgb2JqZWN0cyBpbiBSLgogIDMuIERpZmZlcmVudCBkYXRhIHN0cnVjdHVyZXMgaW4gUi4KICA0LiBIb3cgdG8gZ2V0IHRvIHNpbmdsZSBlbGVtZW50cyB3aXRoaW4gZGF0YSBzdHJ1Y3R1cmVzLgogIDUuIFdvcmtpbmcgd2l0aCBkYXRhIGZyYW1lcy4KICA2LiBIb3cgdG8gbG9hZCBhIGRhdGEgc2V0IGludG8gUi4KICA3LiBIb3cgdG8gbWFrZSBuaWNlIGxvb2tpbmcgcGxvdHMgaW4gUi4KCiMjIFdoYXQgeW91IHdpbGwgZG8gaW4geW91ciBob21ld29yay4KClRoZSBmaXJzdCBsYWIgc2Vzc2lvbiBhbmQgdGhpcyBzY3JpcHQgc2hvdWxkIGVxdWlwIHlvdSB3aXRoIGFsbCB0aGUgdG9vbHMgKGFuZCBsaW5lcyBvZiBjb2RlKSB0byB0YWNrbGUgdGhlIGZpcnN0IGhvbWV3b3JrIGFzc2lnbm1lbnQuCgo+ICA8aSBjbGFzcz0iZmEgZmEtZ3JhZHVhdGlvbi1jYXAiPjwvaT4gQ29weSB0aGUgbGluZXMgb2YgY29kZSB0aGF0IHdvcmtlZCBmb3Igc29tZXRoaW5nIHNpbWlsYXIuIFRoZW4sIGFkanVzdCB0aGUgY29kZSBhY2NvcmRpbmcgdG8geW91ciBwcm9ibGVtLgoKU3Vic3RhbnRpYWxseSwgaW4geW91ciBob21ld29yayB5b3Ugd2lsbCBpbnNwZWN0IGEgZGF0YSBzZXQgb24gVVMgcHJlc2lkZW50aWFsIGVsZWN0aW9ucy4gWW91IHdpbGwgY2FsY3VsYXRlIHNvbWUgbWVhc3VyZXMgb2YgY2VudHJhbCB0ZW5kZW5jeSBhbmQgdmFyaWFiaWxpdHkuIEZpbmFsbHksIHlvdSB3aWxsIHByb2R1Y2Ugc29tZSBuaWNlIHBsb3RzLgoKSXQgaXMgYmVzdCB0byBnZXQgc3RhcnRlZCB3aXRoIHlvdXIgaG9tZXdvcmsgYXMgc29vbiBhcyBwb3NzaWJsZSAoYWZ0ZXIgaXQgd2FzIGhhbmRlZCBvdXQgb24gVHVlc2RheSkuIAoKVHJ5IHRvIHdyaXRlIHRoZSBSIENvZGUgZmlyc3QuIFdlIHdpbGwgcHJvdmlkZSB5b3UgYSBgLlJtZGAgdGVtcGxhdGUgdG8gaGFuZCBpbiB5b3VyIHJlc3VsdHMuCgpJbiBvcmRlciB0byBwYXNzIHRoZSBob21ld29yayBhc3NpZ25tZW50IHlvdSBuZWVkIHRvIHRhY2tsZSBBTEwgcHJvYmxlbXMgb2YgYSBwcm9ibGVtIHNldC4gRm9yIGEgcGFzcyB5b3UgYWxzbyBuZWVkIHRvIGdldCBtb3N0IG9mIHRoZSBwcm9ibGVtcyByaWdodCAob3IgYXQgbGVhc3Qgc2hvdyB1cyB0aGF0IHlvdSB0cmllZCBldmVyeXRoaW5nIHRvIGdldCBpdCByaWdodC4pCgoKIyMjIENsb3NpbmcgcmVtYXJrcy4KCklmIHlvdSBoYXZlIGFueSBxdWVzdGlvbnMgY29uY2VybmluZyB0aGUgbGVjdHVyZSBvciB0aGUgdHV0b3JpYWwgcGxlYXNlIHBvc3QgdGhlbSB0byB0aGUgSUxJQVMgZm9ydW0gb3Igb24gU2xhY2suIFdlIHdpbGwgYW5zd2VyIHRoZW0gb24gYSByZWd1bGFyIGJhc2lzLgoKRG8gbm90IGhlc2l0YXRlIHRvIGNvbWUgdG8gdGhlIG9mZmljZSBob3VycyEKCkFuZCBhbHdheXMgcmVtZW1iZXIgaWYgeW91IGhhdmUgYSBxdWVzdGlvbiwgaXQgaXMgbmV2ZXIgYSBzdHVwaWQgcXVlc3Rpb24uIEluIGZhY3QgbW9zdCBvZiB5b3VyIGZlbGxvdyBzdHVkZW50cyBwcm9iYWJseSBoYXZlIHRoZSBzYW1lIG9yIGEgc2ltaWxhciBxdWVzdGlvbi4gQnkgYXNraW5nIGl0LCBldmVyeW9uZSBpbiB0aGlzIGNsYXNzIHdpbGwgcHJvZml0Lgo=